Java synchronized 底层实现,原理,面试题总结

本文详细探讨了Java中的`synchronized`关键字,包括其底层实现,如偏斜锁、轻量级锁和重量级锁的变化过程。还介绍了管程模型的三种类型:Hasen、Hoare和MESA模型。此外,文章对比了`synchronized`与`ReentrantLock`的区别,并分析了两者在不同场景下的适用性。同时,文章讨论了锁的升级/降级、类锁与对象锁的区别,以及`wait`与`sleep`的差异,并给出了常见的面试题目。
摘要由CSDN通过智能技术生成

底层实现

synchronized底层实现

详细参考:杨晓峰极客时间上的课程《Java核心技术面试精讲》:第16讲 | synchronized底层如何实现?什么是锁的升级、降级

  • synchronized 代码块是由一对儿 monitorenter/monitorexit 指令实现的,Monitor 对象是同步的基本实现单元。

  • 发展历程:

    • JDK6之前,Monitor 的实现完全是依靠操作系统内部的互斥锁,因为需要进行用户态到内核态的切换,所以同步操作是一个无差别的重量级操作。(@所以说效率低下嘛)
    • 现代的(Oracle)JDK 中,JVM 对此进行了大刀阔斧地改进,提供了三种不同的 Monitor 实现,也就是常说的三种不同的锁:偏斜锁(Biased Locking)、轻量级锁和重量级锁大大改进了其性能。
  • 偏斜锁:JVM 会利用 CAS 操作(compare and swap),在对象头上的 Mark Word 部分设置线程 ID,以表示这个对象偏向于当前线程,所以并不涉及真正的互斥锁

  • 轻量级锁:

    • 如果有另外的线程试图锁定某个已经被偏斜过的对象,JVM 就需要撤销(revoke)偏斜锁,并切换到轻量级锁实现。轻量级锁依赖 CAS 操作 Mark Word 来试图获取锁,如果重试成功,就使用普通的轻量级锁;否则,进一步升级为重量级锁。
    • 因为重量级锁性能差,所以轻量级锁又衍生出了一种锁:自旋锁,其实现就是自循环若干次,通过CAS操作MARK WROD试图获取锁

其他锁模型

详细参考:王宝令极客时间上的课程《Java并发编程实战》- 08 | 管程:并发编程的万能钥匙

  • 管程模型:
    • Hasen模型:要求 notify() 放在代码的最后,这样 T2 通知完 T1 后,T2 就结束了,然后 T1 再执行,这样就能保证同一时刻只有一个线程执行。
    • Hoare模型:T2 通知完 T1 后,T2 阻塞,T1 马上执行;等 T1 执行完,再唤醒 T2,也能保证同一时刻只有一个线程执行。但是相比 Hasen 模型,T2 多了一次阻塞唤醒操作。
    • MESA模型(JAVA参考实现):MESA 管程里面,T2 通知完 T1 后,T2 还是会接着执行,T1 并不立即执行,仅仅是从条件变量的等待队列进到入口等待队列里面。这样做的好处是 notify() 不用放到代码的最后,T2 也没有多余的阻塞唤醒操作。但是也有个副作用,就是当 T1 再次执行的时候,可能曾经满足的条件,现在已经不满足了,所以需要以循环方式检验条件变量。—也就是产生假唤醒

锁变化

升级/膨胀

其实就是偏斜锁=》轻量级锁=》重量级锁的过程,见第一节 #底层实现

锁降级

锁降级确实是会发生的,当 JVM 进入安全点(SafePoint)的时候,会检查是否有闲置的 Monitor,然后试图进行降级。

synchronized锁的范围

  • 范围
    • 代码块
    • 方法
    • 对象
  • 对象锁和类
    • 类锁和对象锁是分开的,(现在只是个概念,用来区分对象锁的,是指静态方法的锁),程序中获得类锁的同时也可以获得对象锁。
    • 同一个类锁和同一个类锁是互斥的,同一个对象锁和同一个对象锁互斥。 非静态方法不受类锁的影响
    • 对象锁与实例对象相关, 不同的对象的对象锁不一样,可以同时获取两个不同对象的对象锁
package com.keven;

//类锁和对象锁的测试代码
public class SyncTest {
   

    public static void main(String[] args) throws Exception {
   
        runObjectLockTest();
        System.out.println("finished runObjectLockTest");
        runClassLockTest();
        System.out.println("finished runClassLockTest");
        runClassObjectLockTest();
        System.out.println("finished runClassObjectLockTest");
        Thread.sleep(10000);
    }

 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值