java synchronized 的实现原理与应用

1.6 之后为了减少获得锁和释放锁带来的性能消耗,引入了偏向锁和轻量级锁。他们之间只能升级不能降级,目的时为了提高锁获得和释放的效率。
无锁 -> 偏向锁 -> 轻量级锁 -> 重量级锁
synchronized 可以用在三个地方
method 锁的是当前的实例对象
static method 锁的是类对象
方法快 锁括号里面的对象。
synchronized 通过monitor 对象的进入和推出控制锁,进入时获得锁,退出或异常时释放锁。
同步代码块通过monitorentor和monitorexit指令实现。java 为每个对象都分配了一个monitor 对象与之关联,当monitor 对象被持有后,将处于锁定状态。线程执行到monitorenter 指令时,将尝试获取对象所对应的monitor 的所有权。
对象头中有一个字宽的 Mark Word 32/64位,里面存储了锁的信息。截图来自(https://blog.csdn.net/lengxiao1993/article/details/81568130)
在这里插入图片描述
由图可以看出在MarkWord 部分有一位代表了是否时偏向锁(0:否,1:是),用两位来表示锁的种类。(00:轻量级锁,01:偏向锁或者无锁,10:重量级锁,11:标记为GC)
其中不同的级别的锁,MarkWord中的其他位表示的也不一样。
一、偏向锁:不存在多线程竞争,总是由同一个线程多次获得,让线程获得所的代价更低。
偏向锁会将当前线程的线程id 放到MarkWord 中,当多次获得锁时不需要CAS的操作来加锁,只需要测试当前线程ID是否在MarkWord 中,如果在则表示当前线程已经获得了锁;如果不是,则需要测试一下MarkWord 中的偏向锁标志位是否为1,如果是,则尝试使用CAS将当前线程ID 设置到MarkWord中;如果不是1,则使用CAS竞争锁。
偏向锁撤销流程:偏向锁不会主动释放,是需要竞争的时候才会释放。

  1. 线程2来竞争锁对象;
    
  2. 判断当前对象头是否是偏向锁;
    
  3. 判断拥有偏向锁的线程1是否还存在;
    
  4. 线程1不存在,直接设置偏向锁标识为0(线程1执行完毕后,不会主动去释放偏向锁);
    
  5. 使用cas替换偏向锁线程ID为线程2,锁不升级,仍为偏向锁;
    
  6. 线程1仍然存在,暂停线程1;
    
  7. 设置锁标志位为00(变为轻量级锁),偏向锁为0;
    
  8. 从线程1的空闲monitor record中读取一条,放至线程1的当前monitor record中;
    
  9. 更新mark word,将mark word指向线程1中monitor record的指针;
    
  10.    继续执行线程1的代码;
    
  11. 锁升级为轻量级锁;
    
  12.    线程2自旋来获取锁对象;
    

在这里插入图片描述
二、轻量级锁:
桢栈中创建用于存储锁记录的空间,会将对象头中的MarkWord 中的i内容复制进去,官方称为 Displaced Mark Word.然后线程尝试使用CAS 将对象头中的MarkWord修改为 指向锁记录的指针。如果成功,当前线程获得锁,如果失败,表示其他线程竞争锁,当前线程便使用自旋来获取锁。
释放锁:释放锁时会使用原子的CAS 操作将Displaced Mark Word 替换回到对象头,如果成功,则表示没有竞争发生,如果失败,则表示当前锁存在竞争,锁就会膨胀为重量级锁。
在这里插入图片描述
锁的优缺点对比:
偏向锁:加锁解锁不需要额外的消耗,与执行非同步方法相比仅存在纳秒级的差距。
轻量级锁:竞争的线程不会阻塞,提高程序的响应速度
重量级锁:线程竞争不适用自旋,不会消耗CPU
缺点:
偏向锁:线程间存在锁竞争,会带来额外的锁撤销的消耗
轻量级锁:如果始终得不到锁竞争的线程,会使用自旋消耗CPU
重量级锁:线程阻塞,相应时间缓慢。
使用场景:
偏向锁:适用于只有一个线程访问的同补场景。
轻量级锁:追求响应时间,并且同步块执行时间段。
重量级锁:追求吞吐量,同步执行块执行时间较长。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值