synchronized底层原理,关于无锁、偏向锁、轻量级锁、重量级锁问题
public static void main(String[] args) throws InterruptedException { //HotSpot 虚拟机在启动后有个 4s 的延迟才会对每个新建的对象开启偏向锁模式 Thread.sleep(5000); Object obj = new Object(); System.out.println("匿名偏向状态 =====================" + "\n" + ClassLayout.parseInstance(obj).toPrintable()); new Thread(() -> { synchronized (obj) { System.out.println(Thread.currentThread().getName() + "获取锁执行中。。。\n" + ClassLayout.parseInstance(obj).toPrintable()); } }, "thread-a").start(); // 这段代码未注释时会出现两种结果: // 结果1:初始化偏向锁(未偏向)-->偏向锁(线程A)->偏向锁(线程B) // 结果2:初始化偏向锁(未偏向)-->偏向锁(线程A)->轻量级锁(线程B)->无锁 // 代码注释也会有两种结果: // 结果1:初始化偏向锁(未偏向)-->偏向锁(线程A)->重量级锁(线程B)->无锁 // 结果2:初始化偏向锁(未偏向)-->重量级锁(线程A)->重量级锁(线程B)->无锁 Thread.sleep(1000); new Thread(() -> { synchronized (obj) { System.out.println(Thread.currentThread().getName() + "获取锁执行中。。。\n" + ClassLayout.parseInstance(obj).toPrintable()); } }, "thread-b").start(); // 睡眠5s后 Thread.sleep(5000); System.out.println(Thread.currentThread().getName() + ClassLayout.parseInstance(obj).toPrintable()); }
Thread.sleep(1000); // 这段代码未注释时会出现两种结果: // 结果1:初始化偏向锁(未偏向)-->偏向锁(线程A)->偏向锁(线程B) // 结果2:初始化偏向锁(未偏向)-->偏向锁(线程A)->轻量级锁(线程B)->无锁 // 代码注释也会有两种结果: // 结果1:初始化偏向锁(未偏向)-->偏向锁(线程A)->重量级锁(线程B)->无锁 // 结果2:初始化偏向锁(未偏向)-->重量级锁(线程A)->重量级锁(线程B)->无锁**以上代码JDK版本1.8**看了网上很多视频和文章的分析,总结下来是大多数讲的没那么深,而且有一些细节地方每篇文章可能分析的都不一样,参考那些技术的分析还是没有弄懂为什么会产生这几种不同的结果,底层的锁升级逻辑到底是怎样的呢,有没有大佬帮忙仔细分析下呢,如果能带着一起看源码那最好了......
匿名偏向状态 ===================== java.lang.Object object internals: OFFSET SIZE TYPE DESCRIPTION VALUE 0 4 (object header) 01 00 00 00 (00000001 00000000 00000000 00000000) (1) 4 4 (object header) 00 00 00 00 (00000000 00000000 00000000 00000000) (0) 8 4 (object header) 58 0d 00 00 (01011000 00001101 00000000 00000000) (3416) 12 4 (loss due to the next object alignment)Instance size: 16 bytesSpace losses: 0 bytes internal + 4 bytes external = 4 bytes total thread-a获取锁执行中。。。 java.lang.Object object internals: OFFSET SIZE TYPE DESCRIPTION VALUE 0 4 (object header) d0 f3 7f 2b (11010000 11110011 01111111 00101011) (729805776) 4 4 (object header) e3 00 00 00 (11100011 00000000 00000000 00000000) (227) 8 4 (object header) 58 0d 00 00 (01011000 00001101 00000000 00000000) (3416) 12 4 (loss due to the next object alignment)Instance size: 16 bytesSpace losses: 0 bytes internal + 4 bytes external = 4 bytes total thread-b获取锁执行中。。。 java.lang.Object object internals: OFFSET SIZE TYPE DESCRIPTION VALUE 0 4 (object header) 40 f0 2f 2b (01000000 11110000 00101111 00101011) (724561984) 4 4 (object header) e3 00 00 00 (11100011 00000000 00000000 00000000) (227) 8 4 (object header) 58 0d 00 00 (01011000 00001101 00000000 00000000) (3416) 12 4 (loss due to the next object alignment)Instance size: 16 bytesSpace losses: 0 bytes internal + 4 bytes external = 4 bytes totalmainjava.lang.Object object internals: OFFSET SIZE TYPE DESCRIPTION VALUE 0 4 (object header) 01 00 00 00 (00000001 00000000 00000000 00000000) (1) 4 4 (object header) 00 00 00 00 (00000000 00000000 00000000 00000000) (0) 8 4 (object header) 58 0d 00 00 (01011000 00001101 00000000 00000000) (3416) 12 4 (loss due to the next object alignment)Instance size: 16 bytesSpace losses: 0 bytes internal + 4 bytes external = 4 bytes total
我运行几次都是这个样子,高版本的jvm 已经废弃了偏向锁。所以结果比较符合预期,依次为 01,00,00,01 无锁,轻量级锁,轻量级锁,无锁。这样,就很符合预期了,要不就别纠结偏向锁了吧。
主要内容:一、synchronized的使用方式,二、synchronized锁的原理,三、synchronized锁的优化,四、Lock锁与synchronized一、synchronized的使用方式 在语法上,要使用synchronized关键字,需要把任意一个非null对象作为"锁"对象,也就是需要一个对象监视器(Object Monitor)。总的来说有三种用法: 1.1 作用在实例方法 修饰实例方法,相当于对当前实例对象this加锁,this作为对象监视器。 1.2 作用在静态方法
主要内容:一、synchronized的使用方式,二、synchronized锁的原理,三、synchronized锁的优化,四、Lock锁与synchronized一、synchronized的使用方式 在语法上,要使用synchronized关键字,需要把任意一个非null对象作为"锁"对象,也就是需要一个对象监视器(Object Monitor)。总的来说有三种用法: 1.1 作用在实例方法 修饰实例方法,相当于对当前实例对象this加锁,this作为对象监视器。 1.2 作用在静态方法
synchronized 锁升级原理:在锁对象的对象头里面有一个 threadid 字段,在第一次访问的时候 threadid 为空,jvm 让其持有偏向锁,并将 threadid 设置为其线程 id,再次进入的时候会先判断 threadid 是否与其线程 id 一致,如果一致则可以直接使用此对象,如果不一致,则升级偏向锁为轻量级锁,通过自旋循环一定次数来获取锁,执行一定次数之后,如果还没有正常获
本文向大家介绍多线程中 synchronized 锁升级的原理是什么?相关面试题,主要包含被问及多线程中 synchronized 锁升级的原理是什么?时的应答技巧和注意事项,需要的朋友参考一下 synchronized 锁升级原理:在锁对象的对象头里面有一个 threadid 字段,在第一次访问的时候 threadid 为空,jvm 让其持有偏向锁,并将 threadid 设置为其线程 id,再
本文向大家介绍讲一下 synchronized 关键字的底层原理 ?相关面试题,主要包含被问及讲一下 synchronized 关键字的底层原理 ?时的应答技巧和注意事项,需要的朋友参考一下 synchronized 是由一对 monitorenter/monitorexit 指令实现的,monitor 对象是同步的基本实现单元。 在 Java 6 之前,monitor 的实现完全是依靠操作系统内
主要内容:一、写在前面,二、ReentrantLock和AQS的关系,三、ReentrantLock加锁和释放锁的底层原理,四、总结一、写在前面 上一篇文章聊了一下java并发中常用的原子类的原理和Java 8的优化,具体请参见文章:《为什么程序员招聘都要5年经验起?因为他们懂Java8底层优化!》。 这篇文章,我们来聊聊面试的时候比较有杀伤力的一个问题:聊聊你对AQS的理解? 之前有同学反馈,去互联网公司面试,面试官聊到并发时就问到了这个问题。当时那位同学内心估计受到了一万点伤害。。。 因为首