Synchronized锁的升级

目录

什么是锁升级

什么是锁消除

什么是锁粗化

什么是Mark Word

锁升级的过程


 

什么是锁升级

 

使用Synchronized会让其他线程阻塞,这样很影响程序的总体效率。因此jdk1.6以后优化了Synchronized机制即——锁升级

锁升级的过程为:无锁=》偏向锁=》轻量级锁=》重量级锁

注意:锁是不会降级的!

 

 

什么是锁消除

 

假如你在一个方法中用到了锁,但JVM并没有检查到有共享数据竞争的问题,为了减少性能损耗,JVM会把你的这个锁消除掉

 

 

什么是锁粗化

 

让锁的作用范围尽可能的小,这样可以让锁内代码尽可能少,缩短锁的持有时间。

但锁粗化并不都是有益的。比如有一个for循环,你频繁在for循环里面上锁,释放锁非常影响性能

 

什么是Mark Word

 

Mark Word用来存储对象运行时数据,用来记录对象运行时的一些参数,如:GC年龄,HashCode,锁标志,栈中的指针等

 

 

锁升级的过程

 

1.当没有对象上锁,对象为普通的对象。锁标志位为01,偏向锁标志为0

2.当对象被当作同步锁(Synchronized),假如线程A抢到了。锁标志依然为01,偏向锁标志变为1,此时锁升级为偏向锁。

偏向锁意味着如果再次进入或者退出同一段同步代码块,并不在需要进行加锁或解锁

3.当线程A再次试图获取锁时,JVM发现同步锁对象标志位是01,偏向锁标志为1。MarkWord会记录线程id就是A的id,表示A可以执行同步代码块。

4.当线程B尝试获取锁,JVM发现已经有人占用了,并且线程ID不是B的ID,因此B会先用CAS尝试比较并交换,成功则B获得锁,失败B会进入自旋。

5.B失败后说明锁存在竞争,这样就会导致”偏向锁升级为轻量级锁“。B会再次和A进行CAS比较并交换

6.如果轻量级锁后B仍然抢锁失败,就会使用自旋锁循环,自旋次数由JVM决定。如果某一时间成功,B获得锁。

7.如果B仍然抢锁失败,轻量级锁会升级为重量级锁,标志位改成10,在这个状态下未抢到锁的线程都会被阻塞,并由操作系统底层的Monitor来管理,这样就会出现CPU用户态和内核态的切换,会消耗资源——又名”重量级锁“

 

一个对象刚开始实例化的时候,没有任何线程来访问它。它是可偏向的,意味着它现在认为只可能有一个线程访问它,因此第一个线程访问它之后会偏向第一个线程,这个线程在执行偏向锁操作时使用了CAS,将对象头的ThreadID改成自己的ID,之后再次访问这个对象只需要比较ID,而不需要再使用CAS进行操作。

 

一旦有第二个线程访问这个对象,因为偏向锁不会主动释放,所以第二个线程可以看到对象是偏向锁状态。此时该对象已经存在锁竞争了,会检查原来持有该对象锁的线程是否依然存活,如果挂了则可改变成无锁状态,然后重新偏向新的线程,如果原来的线程依然存活,则马上执行那个线程的操作栈,如果仍然持有偏向锁,会被升级成轻量级锁,如果不存在使用了,将对象恢复到无锁的状态,然后重新偏向。

 

轻量级锁认为竞争存在,但是竞争的程度很轻,一般两个线程对于同一个锁的操作都会错开(自旋),当自旋超过一定次数,或一个线程持有锁,一个线程在自旋,这时来了第三个线程,轻量级锁会膨胀为重量级锁,重量级锁使除了拥有锁的线程外的其他线程全部阻塞,防止CPU空转

你可能感兴趣的:([线程与并发])