synchronized 的超多干货!(三)

简介: synchronized 这个关键字的重要性不言而喻,几乎可以说是并发、多线程必须会问到的关键字了。synchronized 会涉及到锁、升级降级操作、锁的撤销、对象头等。所以理解 synchronized 非常重要,本篇文章就带你从 synchronized 的基本用法、再到 synchronized 的深入理解,对象头等,为你揭开 synchronized 的面纱。

重量级锁

重量级锁其实就是 synchronized 最终加锁的过程,在 JDK 1.6 之前,就是由无锁 -> 加锁的这个过程。

重量级锁的获取流程

  1. 接着上面偏向锁的获取过程,由偏向锁升级为轻量级锁,执行下一步
  2. 会在原持有偏向锁的线程的栈中分配锁记录,将对象头中的 Mark Word 拷贝到原持有偏向锁线程的记录中,原持有偏向锁的线程获得轻量级锁,然后唤醒原持有偏向锁的线程,从安全点处继续执行,执行完毕后,执行下一步,当前线程执行第 4 步
  3. 执行完毕后,开始轻量级解锁操作,解锁需要判断两个条件
  • 判断对象头中的 Mark Word 中锁记录指针是否指向当前栈中记录的指针

微信图片_20220416175621.png

  • 拷贝在当前线程锁记录的 Mark Word 信息是否与对象头中的 Mark Word 一致。

如果上面两个判断条件都符合的话,就进行锁释放,如果其中一个条件不符合,就会释放锁,并唤起等待的线程,进行新一轮的锁竞争。

  1. 在当前线程的栈中分配锁记录,拷贝对象头中的 MarkWord 到当前线程的锁记录中,执行 CAS 加锁操作,会把对象头 Mark Word 中锁记录指针指向当前线程锁记录,如果成功,获取轻量级锁,执行同步代码,然后执行第3步,如果不成功,执行下一步
  2. 当前线程没有使用 CAS 成功获取锁,就会自旋一会儿,再次尝试获取,如果在多次自旋到达上限后还没有获取到锁,那么轻量级锁就会升级为 重量级锁

微信图片_20220416175628.png

如果用流程图表示是这样的

微信图片_20220416175631.png

根据上面对于锁升级细致的描述,我们可以总结一下不同锁的适用范围和场景。

微信图片_20220416175634.png

synchronized 代码块的底层实现

为了便于方便研究,我们把 synchronized 修饰代码块的示例简单化,如下代码所示

public class SynchronizedTest {
    private int i;
    public void syncTask(){
        synchronized (this){
            i++;
        }
    }
}

我们主要关注一下 synchronized 的字节码,如下所示

微信图片_20220416175638.png

从这段字节码中我们可以知道,同步语句块使用的是 monitorenter 和 monitorexit 指令,其中 monitorenter 指令指向同步代码块的开始位置,monitorexit 指令指向同步代码块的结束位置。

那么为什么会有两个 monitorexit 呢?

不知道你注意到下面的异常表了吗?如果你不知道什么是异常表,那么我建议你读一下这篇文章

看完这篇Exception 和 Error,和面试官扯皮就没问题了

synchronized 修饰方法的底层原理

方法的同步是隐式的,也就是说 synchronized 修饰方法的底层无需使用字节码来控制,真的是这样吗?我们来反编译一波看看结果

public class SynchronizedTest {
    private int i;
    public synchronized void syncTask(){
        i++;
    }
}

这次我们使用 javap -verbose 来输出详细的结果

微信图片_20220416175644.png

从字节码上可以看出,synchronized 修饰的方法并没有使用 monitorenter 和 monitorexit 指令,取得代之是ACC_SYNCHRONIZED 标识,该标识指明了此方法是一个同步方法,JVM 通过该 ACC_SYNCHRONIZED 访问标志来辨别一个方法是否声明为同步方法,从而执行相应的同步调用。这就是 synchronized 锁在同步代码块上和同步方法上的实现差别。

目录
打赏
0
0
0
0
4
分享
相关文章
|
23天前
|
【Java并发】【ReentrantLock】适合初学体质的ReentrantLock入门
前言 什么是ReentrantLock? ReentrantLock 是 Java 并发包 (java.util.concurrent.locks) 中的一个类,它实现了 Lock 接口,提供了与
63 10
【Java并发】【ReentrantLock】适合初学体质的ReentrantLock入门
|
2月前
|
【Java并发】【synchronized】适合初学者体质入门的synchronized
欢迎来到我的Java线程同步入门指南!我不是外包员工,梦想是写高端CRUD。2025年我正在沉淀中,博客更新速度加快,欢迎点赞、收藏、关注。 本文介绍Java中的`synchronized`关键字,适合初学者。`synchronized`用于确保多个线程访问共享资源时不会发生冲突,避免竞态条件、保证内存可见性、防止原子性破坏及协调多线程有序访问。
69 8
【Java并发】【synchronized】适合初学者体质入门的synchronized
|
9月前
|
Java多线程同步大揭秘:synchronized与Lock的终极对决!
Java多线程同步大揭秘:synchronized与Lock的终极对决!
143 5
惊呆了!Java多线程里的“synchronized”竟然这么神奇!
【6月更文挑战第20天】Java的`synchronized`关键字是解决线程安全的关键,它确保同一时间只有一个线程访问同步代码。在案例中,`Counter`类的`increment`方法如果不加同步,可能会导致竞态条件。通过使用`synchronized`方法或语句块,可以防止这种情况,确保线程安全。虽然同步会带来性能影响,但它是构建并发应用的重要工具,平衡同步与性能是使用时需考虑的。了解并恰当使用`synchronized`,能有效应对多线程挑战。
29 1
一文弄懂synchronized
一文弄懂synchronized
113 0
|
12月前
多线程售票demo,用ReentrantLock实现
多线程售票demo,用ReentrantLock实现
谈一谈synchronized和ReentrantLock
谈一谈synchronized和ReentrantLock
91 0
|
12月前
|
java多线程之Lock锁原理以及案例实现电影院卖票
java多线程之Lock锁原理以及案例实现电影院卖票
120 0
synchronized 和 volatile 的区别是什么?(高薪常问)
synchronized 和 volatile 的区别是什么?(高薪常问)
109 2
查漏补缺第二期(synchronized & 锁升级)
前言 目前正在出一个查漏补缺专题系列教程, 篇幅会较多, 喜欢的话,给个关注❤️ ~ 本专题主要以Java语言为主, 好了, 废话不多说直接开整吧~ Q1 & 请说说对synchronized的理解 在Java中,关键字synchronized用于实现多线程之间的同步。它可以应用于方法或代码块,并确保在同一时间只有一个线程可以访问被同步的代码段.

热门文章

最新文章

AI助理

你好,我是AI助理

可以解答问题、推荐解决方案等