java并发之锁的升级

偏向锁 --> 轻量级锁 --> 重量级锁,是synchronized的三种形态转换。

锁可以升级但不能降级,意味着偏向锁升级成轻量级锁后不能降级成偏向锁。这种锁升级却不能降级的策略,目的是为了提高获得锁和释放锁的效率。

线程的状态:

java并发之锁的升级_第1张图片

就绪队列可能随时被CPU选中执行;阻塞队列需要等其他线程释放锁后来通知 重新进入就绪队列。

偏向锁

例如我们的学校网站,同时使用的用户没有多少,并没有竞争,这样的情况没必要每次都加锁释放锁,这时候我们用偏向锁就可以了。synchronized一开始的状态是偏向锁,偏向锁是什么样子呢,加锁执行完后释放不需要通知阻塞队列,下次进来查看是我自己的锁 直接进来就好了。是一个简化的加锁和释放锁的过程。会让性能好很多。

偏向锁适用于没有什么并发的时候。

轻量级锁

同一时刻经常性的出现竞争,使用轻量级锁,即竞争失败后不进入阻塞队列,他的逻辑是有一个死循环,不断对加锁任务进行访问,一旦锁释放 任务立刻执行,同时执行完后加锁速度也非常快。极高频率查看锁的状态非常消耗CPU,但优点也很明显 可以立刻感知锁的释放和加锁。这个循环查看就是cpu自旋。

重量级锁

当高并发的情况,就会使用到阻塞队列,也就是加重量级锁,当竞争失败后进入阻塞队列,等另一个线程完全释放锁后 去阻塞队列通知,再将任务加入就绪队列。这样相比于轻量级锁大大降低了CPU的损耗。

锁的优缺点比较

java并发之锁的升级_第2张图片

CAS替换操作细讲

总线一次性传输36-41bit,替换的头部有64bit,需要传输两次(分低32和高32)。

如果出现低32位更新后,高32位还未更新的空档期,时间片出现替换,其他线程发现你没有锁 给你标记为锁,这样整体结构就会发生改变。

所以持有锁也不一定是安全的,关键在于总线位数不到64位。为了防止这样的现象,更新前应该将总线锁住。

你可能感兴趣的:(java,开发语言)