您的位置:首页 > 编程语言 > Java开发

偏向锁,轻量级锁,重量级锁

2016-07-06 20:31 561 查看

偏向锁,轻量级锁,重量级锁

标签(空格分隔): java 并发 锁

偏向锁

偏向锁,顾名思义,它会偏向于第一个访问锁的线程,如果在接下来的运行过程中,该锁没有被其他的线程访问,则持有偏向锁的线程将永远不需要触发同步。

如果在运行过程中,遇到了其他线程抢占锁,则持有偏向锁的线程会被挂起,JVM会尝试消除它身上的偏向锁,将锁恢复到标准的轻量级锁。(偏向锁只能在单线程下起作用),其流程如图所示


下面的表显示了Markword的状态,

锁状态25bits + 4bits + 1bittag bits
轻量级锁指向栈中锁记录的指针00
重量级锁指向互斥量(重量级锁)的指针10
GC标记11
偏向锁线程ID+Epoch+age+101

轻量级锁

轻量级锁(Lightweight Locking)本意是在没有多线程竞争的前提下,减少传统的重量级锁使用操作系统互斥量产生的性能消耗,是为了减少多线程进入互斥的几率,并不是要替代互斥。

它利用了CPU原语Compare-And-Swap(CAS,汇编指令CMPXCHG),尝试在进入互斥前,进行补救。通过上表我们可以知道00标记为轻量级锁,其流程如图所示


虚拟机使用CAS操作尝试将对象的MarkWord更新为指向LockRecord的指针,如果这个更新成功了,那么这个线程就拥有该对象的锁,并且对象的所标识为便成为00,表示处于轻量级锁定状态。如下图所示


如果更新失败,并且锁对象被其它线程抢占了,则如果有连个以上的线程争用同一个锁,那么轻量级锁不再有效,要膨胀为重量级锁。

解锁过程也是通过CAS操作进行的,如果对象的markword仍然指向线程的所记录,那么就用CAS操作把对象当前的Markword和线程中复制的displaced markword替换回来,如果成功,则整个同步过程完成了, 失败则说明其他线程尝试获取该所,那就要在释放锁的同时,唤醒被挂起的线程。

三种锁的对比

优点缺点使用场景
偏向锁加锁和解锁不需要额外的消耗,和执行非同步方法相比仅存在纳秒级的差距如果线程间存在锁竞争,会带来额外的锁撤销的消耗适用于只有一个线程访问同步块场景
轻量级锁竞争的线程不会阻塞,提高了程序的响应速度如果始终得不到锁竞争的线程,使用自旋会消耗CPU追求响应时间同步块执行速度非常快
重量级锁线程竞争不使用自旋,不会消耗CPU线程阻塞,响应时间缓慢追求吞吐量,同步块执行速度较快
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  java 并发