synchronized的锁升级(偏向锁,自旋锁(cas),重量级锁)
Posted nmwyqw
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了synchronized的锁升级(偏向锁,自旋锁(cas),重量级锁)相关的知识,希望对你有一定的参考价值。
synchronzied是一个重量级锁
概念:什么叫重量级锁?
就是申请资源必须经过kernel(内核也叫操作系统),调用。
(里面涉及到了用户态(用户空间)和内核态(os)的交互)
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
轻量级锁:是不经过操作系统。
cas:乐观锁(compare and swap)比较与交换(可以翻看Atomic原子类里源码)
cas中的问题ABA
虽然,cas回成功但是也会带来一些隐患(如下连接)
https://blog.csdn.net/aigoogle/article/details/38533047
解决方法怎么
在给对象加时间戳,版本号等都可以操作
原子类
在c++的代码里,有一条汇编语言支持cas
但是,这条cmpchg1不具有原子性,点进lock_if_mp(%4)里
最终实现是lock cmpxchg 指令:表示在硬件在执行后面的指令会锁定一个北桥总线。(相当于锁定总线,但是比锁总线要轻量级)解决了下面的问题
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
java对象在内存中的布局(导入工具:jol=java object layout)java对象布局
<dependency>
<groupId>org.openjdk.jol</groupId>
<artifactId>jol-core</artifactId>
<version>0.9</version>
</dependency>
我们可以理解为对象存放在堆里是一块一块的,每一块都有布局:如图
所谓的对象上锁就是锁对象的头,所谓的锁升级就是了解markword的变化
jdk团队统计在jdk类库里一些方法的提供synchronized的方法,大部分情况下对是在一个线程里运行,如果一直是重量级锁会消耗大量资源提出优化
偏向锁:(jvm默认打开并在jvm启动后4秒启动)如stringbuffer里面的大部分方法是安全的,如果在同一个线程里运行,就会出现上面的情况,那么jdk做法是当一个线程第一的到这把锁,我们就认为这个锁偏向于它,实际的做法是把线程的放到了对象的对象头里。(偏向锁到轻量级只要由竞争就之间升级)
偏向锁为什么默认在jvm启动后4秒才启动,因为,当jvm刚运行的时候,里面有很多syn的方法,如果还是由偏向锁再到自旋锁,这样会消耗大量资源。所以jvm既然知道是多线程,所以直接跳过了偏向锁,转变为自旋锁。
让jvm延迟4秒启动,观察markword
自旋锁:(支持锁锁重入)假如有两个线程同时,抢一把锁,这个时候,谁第一个抢到,就把它的id放在对象的markword上。这个过程是while(操作)
重量级锁:当线程竞争激烈,比如有10000个线程。这个时候如果还是自旋的话,会消耗大量的cpu,所以这个时候需要升级成重量级锁。
重量级锁和轻量级锁,最大的区别是,重量级需要经过os(操作系统),并且它还是提供队列,其中(waitset)存放等待的队列,让它们在里面排队,(entrylist)存放竞争的队列
(什么时候轻量级会升级到重量级呢)
jdk1.6之前是自旋超过10次,或者等待线程超过cpu核数的2分之一,自动升级
jdk1.6以后是jdk出来自适应自旋,它会自己判断什么时候升级。
以上是关于synchronized的锁升级(偏向锁,自旋锁(cas),重量级锁)的主要内容,如果未能解决你的问题,请参考以下文章