Java并发-synchronized使用方法
创始人
2024-04-13 13:55:44
0

synchronized 关键字介绍

  • Java 中的每个对象都可以把它当作一个同步锁来使用,这些 Java 内置的使用者看不到的锁被称为内部锁,也叫作监视器锁。
  • 代码在进入 synchronized 代码块前会自动获取内部锁,这时候其他线程访问该同步代码块时会被阻塞挂起。拿到内部锁的线程会在正常退出同步代码块或者抛出异常后或者在同步块内调用了该内置锁资源的 wait 系列方法时释放该内置锁。
  • 内置锁:即排它锁,也就是当一个线程获取这个锁后,其他线程必须等待该线程释放锁后才能获取该锁。

Tips:由于 Java 中的线程是与操作系统的原生线程一一对应的,所以当阻塞一个线程时,需要从用户态切换到内核态执行阻塞操作,这是很耗时的操作,而 synchronized 的使用就会导致上下文切换。

 synchronized 的三种使用方式

Java 中每一个对象都可以作为锁,这是 synchronized 实现同步的基础。synchronized 的三种使用方式如下:

  • 普通同步方法(实例方法)锁是当前实例对象 ,进入同步代码前要获得当前实例的锁;
  • 静态同步方法锁是当前类的 class 对象 ,进入同步代码前要获得当前类对象的锁
  • 同步方法块:锁是括号里面的对象,对给定对象加锁,进入同步代码库前要获得给定对象的锁。

synchronized 作用于实例方法

场景设计

  • 创建两个线程,分别设置线程名称为 threadOne 和 threadTwo;
  • 创建一个共享的 int 数据类型的 count,初始值为 0;
  • 两个线程同时对该共享数据进行增 1 操作,每次操作 count 的值增加 1;
  • 对于 count 数值加 1 的操作,请创建一个单独的 increase 方法进行实现;
  • increase 方法中,先打印进入的线程名称,然后进行 1000 毫秒的 sleep,每次加 1 操作后,打印操作的线程名称和 count 的值;
  • 运行程序,观察打印结果。

package jvm.juc;public class SynchroizedTest extends Thread{static int count = 0;public synchronized void increaseCount() {String thread = Thread.currentThread().getName();System.out.println("当前" + thread + "线程正在操作");try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}count += 1;System.out.println("当前" + thread + ":" +  count);}@Overridepublic void run() {increaseCount();}public static void main(String[] args) {SynchroizedTest test = new SynchroizedTest();Thread t1 = new Thread(test);Thread t2 = new Thread(test);t1.setName("threadOne");t2.setName("threadTwo");t1.start();t2.start();}}

上述程序运行结果如下图所示

 Tips:仔细看 DemoTest test = new DemoTest () 这就话,我们创建了一个 DemoTest 的实例对象,对于修饰普通方法,synchronized 关键字的锁即为 test 这个实例对象。

 synchronized 作用于静态方法

暂时其他代码不变,然后main函数里面代码改成如下形式

public static void main(String[] args) {SynchroizedTest test = new SynchroizedTest();SynchroizedTest test2 = new SynchroizedTest();Thread t1 = new Thread(test);Thread t2 = new Thread(test2);t1.setName("threadOne");t2.setName("threadTwo");t1.start();t2.start();}

代码执行的结果如下图所示

 可以看出,两个线程同时进入到锁中

两个线程持有两个不同的锁,不会产生互相 block。相信讲到这里,同学对实例对象锁的作用也了解了,那么我们再次将 increase 方法进行修改,将其修改成静态方法,然后输出结果。

 结果如下,又得到了顺序执行

 结果分析:我们看到,结果又恢复了正常,为什么会这样?
关键的原因在于,synchronized 修饰静态方法,锁为当前 class,即 DemoTest.class。

synchronized 作用于同步代码块 

Tips:对于 synchronized 作用于同步代码,锁为任何我们创建的对象,只要是个对象即可,如 new Object () 可以作为锁,new String () 也可作为锁,当然如果传入 this,那么此时代表当前对象。

	/*** synchronized 修饰实例方法*/static final Object objectLock = new Object(); //创建一个对象锁public static void increase() throws InterruptedException {System.out.println(Thread.currentThread().getName() + "获取到锁,其他线程在我执行完毕之前,不可进入。" );synchronized (objectLock) {sleep(1000);count++;System.out.println(Thread.currentThread().getName() + ": " + count);}}

 代码解析:我们创建了一个 objectLock 作为对象锁,除了第一句打印语句,让后三句代码加入了 synchronized 同步代码块,当 threadOne 进入时,threadTwo 不可进入后三句代码的执行。

 

 

相关内容

热门资讯

原创 “... 增值税是我国第一大税种,其纳税人覆盖绝大部分经营主体,与社会大众日常生活息息相关。12月30日,《中...
湖南以高质量涉外法律服务保障高... 近年来,中国(湖南)自贸试验区建设加快推进,中非经贸博览会、中非经贸深度合作先行区等国家级平台相继落...
山东省民办教育协会政策与法律专... 12月27日,山东省民办教育领域迎来一场极具里程碑意义的盛会,山东省民办教育协会政策与法律专家委员会...
我国将继续实施黄河休禁渔制度 记者31日从农业农村部获悉,农业农村部日前印发《关于继续实施黄河休禁渔制度的通告》,明确继续实施黄河...
下调!住房出售,最新政策来了! 12月30日,财政部、税务总局发布《关于个人销售住房增值税政策的公告》(下称《公告》),明确个人将购...
原创 欣... 《电鳗财经》电鳗号/文 欣旺达子公司因动力电池质量纠纷被诉,索赔金额高达数亿元的消息引发行业震动。...
华蓝集团:关联交易按制度审议与... 证券之星消息,华蓝集团(301027)12月30日在投资者关系平台上答复投资者关心的问题。 投资者提...
郑州银行发布诉讼事项进展 被告... 12月31日,郑州银行发布《关于诉讼事项进展的公告》称,2025年7月,郑州银行中原路支行与郑州金威...
2026年嘉兴离婚律师权威推荐... 2026年嘉兴离婚律师权威推荐:北京国樽(嘉兴)律师事务所领衔,专业离婚律师/婚姻律师/诉讼离婚律师...
厦门出台《厦门历史文化名城保护... 集美学村建筑群 12月30日,市人大常委会表决通过《厦门历史文化名城保护条例》《厦门经济特区绿色金融...