加不加 synchronized 有什么区别?

2024-06-14 05:58

本文主要是介绍加不加 synchronized 有什么区别?,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

今天一起来认识认识 synchronized 这个一面试就会被提到的关键字。这一篇不会讲太多理论,主要先熟悉熟悉一下最简单的用法。只讨论一个问题:方法没用 synchronized 和用了 synchronized 有什么区别?

首先我们的理论基础是 synchronized 关键字是用在多线程并发的场景,所以接下来的测试代码都会模拟多线程并发的情况。我们直接通过代码来给大家讲讲加没加 synchronized 的区别。

1. 方法没加 synchronized 关键字

我们先写一个普通到不能再普通的代码,就是一个实例方法,在多线程并发的情况下执行同一个方法。如下所示。

public class NoSynchronizedTest {public static void main(String[] args) {NoSynchronizedTest noSynchronizedTest = new NoSynchronizedTest();for (int i = 0; i < 5; i ++) {Thread thread = new Thread(() -> {noSynchronizedTest.testNoSynchronizedMethod();});thread.start();}}public void testNoSynchronizedMethod() {System.out.println("testNoSynchronizedMethod-start-" + Thread.currentThread().getName());System.out.println("testNoSynchronizedMethod-end-" + Thread.currentThread().getName());}}

运行结果:

我们可以发现如下结论:

  1. 在单线程中,执行顺序是有保证的,也就是每个 start 都优先于 end。
  2. 在多线程中,线程之间的 start 和 end 是没有先后顺序的,先进入方法的线程不一定先执行完方法。我们看运行结果的红色框,5 个线程只有 Thread-2 是完整的执行完方法,没有其他线程乱入的。

2. 方法加 synchronized 关键字

我们对上面的代码稍加修改,在方法上加 synchronized 修饰,并且在两种情况下执行代码。

5 个线程只有一个 synchronizedTest 对象。
public class SynchronizedTest {public static void main(String[] args) {SynchronizedTest synchronizedTest = new SynchronizedTest();for (int i = 0; i < 5; i++) {Thread thread = new Thread(() -> {synchronizedTest.testSynchronizedMethod();});thread.start();}}public synchronized void testSynchronizedMethod() {System.out.println("testSynchronizedMethod-start-" + Thread.currentThread().getName());System.out.println("testSynchronizedMethod-end-" + Thread.currentThread().getName());}
}

运行结果:

5 个线程中,每个线程有各自的 synchronizedTest 对象。
public class SynchronizedTest {public static void main(String[] args) {for (int i = 0; i < 5; i++) {SynchronizedTest synchronizedTest = new SynchronizedTest();Thread thread = new Thread(() -> {synchronizedTest.testSynchronizedMethod();});thread.start();}}public synchronized void testSynchronizedMethod() {System.out.println("testSynchronizedMethod-start-" + Thread.currentThread().getName());System.out.println("testSynchronizedMethod-end-" + Thread.currentThread().getName());}
}

运行结果:

我们可以发现如下结论:

  1. 当 5 个线程中只有一个对象时,5 个线程之间的执行顺序是串行的,互不影响,线程0进入方法后,其他线程就无法再进入方法了,得等待线程0执行完后,其他线程才能进入,并且一次只能有1个线程进入。
  2. 每个线程一个对象时,就不会出现排队的场景,各个线程互不影响,相当于每个线程都有各自的资源,没有互相竞争的关系。

由此,我们可以得出什么呢?synchronized 关键字就是悲观锁的具体实现,在多线程并发竞争同一资源时,实现同一时刻只有一个线程能操作资源。

这篇文章是了解 synchronized 最最最皮毛的知识,对 synchronized 熟悉的朋友可以当做是回顾知识点,不熟悉的朋友可以当做是入门,后面会继续深挖知识点。

如果觉得这篇文章看了有收获,麻烦点个赞,支持一下,原创不易。

推荐阅读

从 JVM 视角看看 Java 守护线程

写了那么多年 Java 代码,终于 debug 到 JVM 了

全网最新最简单的 openjdk13 代码编译

了解Java线程优先级,更要知道对应操作系统的优先级,不然会踩坑

线程最最基础的知识

老板叫你别阻塞了

吃个快餐都能学到串行、并行、并发

泡一杯茶,学一学同异步

进程知多少?

设计模式看了又忘,忘了又看?

后台回复『设计模式』可以获取《一故事一设计模式》电子书

觉得文章有用帮忙转发&点赞,多谢朋友们!

LieBrother

这篇关于加不加 synchronized 有什么区别?的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1059570

相关文章

结构体和联合体的区别及说明

《结构体和联合体的区别及说明》文章主要介绍了C语言中的结构体和联合体,结构体是一种自定义的复合数据类型,可以包含多个成员,每个成员可以是不同的数据类型,联合体是一种特殊的数据结构,可以在内存中共享同一... 目录结构体和联合体的区别1. 结构体(Struct)2. 联合体(Union)3. 联合体与结构体的

什么是 Ubuntu LTS?Ubuntu LTS和普通版本区别对比

《什么是UbuntuLTS?UbuntuLTS和普通版本区别对比》UbuntuLTS是Ubuntu操作系统的一个特殊版本,旨在提供更长时间的支持和稳定性,与常规的Ubuntu版本相比,LTS版... 如果你正打算安装 Ubuntu 系统,可能会被「LTS 版本」和「普通版本」给搞得一头雾水吧?尤其是对于刚入

python中json.dumps和json.dump区别

《python中json.dumps和json.dump区别》json.dumps将Python对象序列化为JSON字符串,json.dump直接将Python对象序列化写入文件,本文就来介绍一下两个... 目录1、json.dumps和json.dump的区别2、使用 json.dumps() 然后写入文

native和static native区别

本文基于Hello JNI  如有疑惑,请看之前几篇文章。 native 与 static native java中 public native String helloJni();public native static String helloJniStatic();1212 JNI中 JNIEXPORT jstring JNICALL Java_com_test_g

Android fill_parent、match_parent、wrap_content三者的作用及区别

这三个属性都是用来适应视图的水平或者垂直大小,以视图的内容或尺寸为基础的布局,比精确的指定视图的范围更加方便。 1、fill_parent 设置一个视图的布局为fill_parent将强制性的使视图扩展至它父元素的大小 2、match_parent 和fill_parent一样,从字面上的意思match_parent更贴切一些,于是从2.2开始,两个属性都可以使用,但2.3版本以后的建议使

Collection List Set Map的区别和联系

Collection List Set Map的区别和联系 这些都代表了Java中的集合,这里主要从其元素是否有序,是否可重复来进行区别记忆,以便恰当地使用,当然还存在同步方面的差异,见上一篇相关文章。 有序否 允许元素重复否 Collection 否 是 List 是 是 Set AbstractSet 否

javascript中break与continue的区别

在javascript中,break是结束整个循环,break下面的语句不再执行了 for(let i=1;i<=5;i++){if(i===3){break}document.write(i) } 上面的代码中,当i=1时,执行打印输出语句,当i=2时,执行打印输出语句,当i=3时,遇到break了,整个循环就结束了。 执行结果是12 continue语句是停止当前循环,返回从头开始。

maven发布项目到私服-snapshot快照库和release发布库的区别和作用及maven常用命令

maven发布项目到私服-snapshot快照库和release发布库的区别和作用及maven常用命令 在日常的工作中由于各种原因,会出现这样一种情况,某些项目并没有打包至mvnrepository。如果采用原始直接打包放到lib目录的方式进行处理,便对项目的管理带来一些不必要的麻烦。例如版本升级后需要重新打包并,替换原有jar包等等一些额外的工作量和麻烦。为了避免这些不必要的麻烦,通常我们

ActiveMQ—Queue与Topic区别

Queue与Topic区别 转自:http://blog.csdn.net/qq_21033663/article/details/52458305 队列(Queue)和主题(Topic)是JMS支持的两种消息传递模型:         1、点对点(point-to-point,简称PTP)Queue消息传递模型:         通过该消息传递模型,一个应用程序(即消息生产者)可以

关键字synchronized、volatile的比较

关键字volatile是线程同步的轻量级实现,所以volatile性能肯定比synchronized要好,并且volatile只能修饰于变量,而synchronized可以修饰方法,以及代码块。随着JDK新版本的发布,synchronized关键字的执行效率上得到很大提升,在开发中使用synchronized关键字的比率还是比较大的。多线程访问volatile不会发生阻塞,而synchronize