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 锁在同步代码块上和同步方法上的实现差别。

相关文章
|
8月前
|
安全 Java 开发者
深入解析ReentrantLock重入锁:Java多线程中的利器
深入解析ReentrantLock重入锁:Java多线程中的利器
478 4
|
9月前
|
安全 Java
一文教你,synchronized和Lock的区别?
最近有多位粉丝被问到synchronized和Lock,据说还是阿里一面的面试题。在分布式开发中,锁是控制线程的重要方式。Java提供了两种锁机制synchronized 和 Lock。接下来,我给大家分享一下我对synchronized和Lock的理解。
71 0
|
4月前
|
安全 Java
java多线程之Lock锁原理以及案例实现电影院卖票
java多线程之Lock锁原理以及案例实现电影院卖票
|
7月前
|
传感器 缓存 安全
JUC第六讲:二面阿里竟然败在了 volatile 关键字上
JUC第六讲:二面阿里竟然败在了 volatile 关键字上
|
12月前
|
设计模式 消息中间件 NoSQL
查漏补缺第二期(synchronized & 锁升级)
前言 目前正在出一个查漏补缺专题系列教程, 篇幅会较多, 喜欢的话,给个关注❤️ ~ 本专题主要以Java语言为主, 好了, 废话不多说直接开整吧~ Q1 & 请说说对synchronized的理解 在Java中,关键字synchronized用于实现多线程之间的同步。它可以应用于方法或代码块,并确保在同一时间只有一个线程可以访问被同步的代码段.
|
12月前
每日一博 - Semaphore使用场景分析以及源码分析
每日一博 - Semaphore使用场景分析以及源码分析
47 0
|
12月前
|
存储 安全 Java
大白话讲解synchronized锁升级套路
synchronized锁是啥?锁其实就是一个对象,随便哪一个都可以,Java中所有的对象都是锁,换句话说,Java中所有对象都可以成为锁。 这次我们主要聊的是synchronized锁升级的套路
|
安全 Java 开发者
京东面试官:说说synchronized 和 ReentrantLock的区别!
前面我们介绍了很多关于多线程的内容,在多线程中有一个很重要的课题需要我们攻克,那就是线程安全问题。线程安全问题指的是在多线程中,各线程之间因为同时操作所产生的数据污染或其他非预期的程序运行结果。
105 0
|
存储 SQL 安全
面试:为了进阿里,重新翻阅了Volatile与Synchronized
在深入理解使用Volatile与Synchronized时,应该先理解明白Java内存模型 (Java Memory Model,JMM)
141 0
面试:为了进阿里,重新翻阅了Volatile与Synchronized
|
安全 Java
《提升能力,涨薪可待》—Java并发之Synchronized
线程安全是并发编程中的至关重要的,
139 0