偏向锁,轻量级锁,重量级锁
2016-07-06 20:31
561 查看
偏向锁,轻量级锁,重量级锁
标签(空格分隔): java 并发 锁偏向锁
偏向锁,顾名思义,它会偏向于第一个访问锁的线程,如果在接下来的运行过程中,该锁没有被其他的线程访问,则持有偏向锁的线程将永远不需要触发同步。如果在运行过程中,遇到了其他线程抢占锁,则持有偏向锁的线程会被挂起,JVM会尝试消除它身上的偏向锁,将锁恢复到标准的轻量级锁。(偏向锁只能在单线程下起作用),其流程如图所示
下面的表显示了Markword的状态,
锁状态 | 25bits + 4bits + 1bit | tag bits |
---|---|---|
轻量级锁 | 指向栈中锁记录的指针 | 00 |
重量级锁 | 指向互斥量(重量级锁)的指针 | 10 |
GC标记 | 空 | 11 |
偏向锁 | 线程ID+Epoch+age+1 | 01 |
轻量级锁
轻量级锁(Lightweight Locking)本意是在没有多线程竞争的前提下,减少传统的重量级锁使用操作系统互斥量产生的性能消耗,是为了减少多线程进入互斥的几率,并不是要替代互斥。它利用了CPU原语Compare-And-Swap(CAS,汇编指令CMPXCHG),尝试在进入互斥前,进行补救。通过上表我们可以知道00标记为轻量级锁,其流程如图所示
虚拟机使用CAS操作尝试将对象的MarkWord更新为指向LockRecord的指针,如果这个更新成功了,那么这个线程就拥有该对象的锁,并且对象的所标识为便成为00,表示处于轻量级锁定状态。如下图所示
如果更新失败,并且锁对象被其它线程抢占了,则如果有连个以上的线程争用同一个锁,那么轻量级锁不再有效,要膨胀为重量级锁。
解锁过程也是通过CAS操作进行的,如果对象的markword仍然指向线程的所记录,那么就用CAS操作把对象当前的Markword和线程中复制的displaced markword替换回来,如果成功,则整个同步过程完成了, 失败则说明其他线程尝试获取该所,那就要在释放锁的同时,唤醒被挂起的线程。
三种锁的对比
锁 | 优点 | 缺点 | 使用场景 |
---|---|---|---|
偏向锁 | 加锁和解锁不需要额外的消耗,和执行非同步方法相比仅存在纳秒级的差距 | 如果线程间存在锁竞争,会带来额外的锁撤销的消耗 | 适用于只有一个线程访问同步块场景 |
轻量级锁 | 竞争的线程不会阻塞,提高了程序的响应速度 | 如果始终得不到锁竞争的线程,使用自旋会消耗CPU | 追求响应时间同步块执行速度非常快 |
重量级锁 | 线程竞争不使用自旋,不会消耗CPU | 线程阻塞,响应时间缓慢 | 追求吞吐量,同步块执行速度较快 |
相关文章推荐
- java对世界各个时区(TimeZone)的通用转换处理方法(转载)
- java-注解annotation
- java-模拟tomcat服务器
- java-用HttpURLConnection发送Http请求.
- java-WEB中的监听器Lisener
- Android IPC进程间通讯机制
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- 介绍一款信息管理系统的开源框架---jeecg
- 聚类算法之kmeans算法java版本
- java实现 PageRank算法
- PropertyChangeListener简单理解
- c++11 + SDL2 + ffmpeg +OpenAL + java = Android播放器
- 插入排序
- 冒泡排序
- 堆排序
- 快速排序
- 二叉查找树