Synchronized锁原理

 

刚开始Monitor中的Owner为null

当Thread-2执行synchronized(obj)就会将Monitor的所有者Owner置为Thread-2, Monitor中只能有一个Owner

在Thread-2 上锁的过程中,如果Thread-3, Thread-4, Thread-5 也来执行synchronized(bj),就会进入EntryList BIOCKED

Thread-2执行完同步代码块的内容,然后唤醒EntryList中等待的线程来竞争锁,竞争的时是非公平的

图中WaitSet中的Thread-0,Thread-1 是之前获得过锁,但条件不满足进入WAITING状态的线程
注意:

  • synchronized 必须是进入同一个对象的monitor才有上述的效果
  • 不加synchronized的对象不会关联监视器,不遵从以上规则

为什么每一个对象都可以作为锁对象

因为java的底层是由C++实现的,每个对象都会有一个ObjectMonitor(对象监视器),里面存在owner(设置持有锁的当前线程id) entryList(阻塞的线程) waitset(存放处于wait状态的线程队列) recursions(锁的重入次数) count(用来获取该线程获取锁的次数)。

1.轻量级锁

轻量级锁的使用场景:如果一个对象虽然有多线程访问,但多线程访问的时间是错开的(也就是没有竞争) ,那么可以使用轻量级锁来优化。

锁膨胀

如果在尝试加轻量级锁的过程中,CAS 操作无法成功,这时一种情况就是有其它线程为此对象加上了轻量级锁(有竞争), 这时需要进行锁膨胀,将轻量级锁变为重量级锁。

这时Thread-1加轻量级锁失败,进入锁膨胀流程

  • 即为Object对象申请Monitor锁,让Object指向重量级锁地址
  • 然后自己进入Monitor的EntryList BLOCKED
  • 当Thread-0退出同步块解锁时,使用cas将Mark Word的值恢复给对象头,失败。这时会进入重量级解锁流程,即按照Monitor地址找到Monitor对象,设置Owner为null,唤醒EntryList中BLOCKED线程
     

偏向锁

一个对象创建时:

  • 如果开启了偏向锁(默认开启),那么对象创建后,markword 值为0x05即最后3位为101,这时它的thread、epoch、 age 都为0
  • 偏向锁是默认是延迟的,不会在程序启动时立即生效,如果想避免延迟,可以加VM参数-XX:BiasedLockingStartupDelay=0来禁用延迟
  • 如果没有开启偏向锁,那么对象创建后,markword 值为0x01即最后3位为001,这时它的hashcode、age 都为0,第一次用到hashcode时才会赋值

如果是偏向锁,线程加锁成功后,对象markword中会存当前的线程ID,当这个线程尝试再次加锁时,不需要在进行CAS操作,直接比较线程ID即可,如果相同,就加锁成功。

注意:处于偏向锁的对象解锁后,线程ID仍然存储在对象头总。

当调用了偏向对象的hashCode方法之后,对象会解除偏向状态,回归正常状态,因为markword需要储存hashCode的值,没有空间再储存线程ID。

批量重偏向

如果对象虽然被多个线程访问,但没有竞争,这时偏向了线程T1的对象仍有机会重新偏向T2,重偏向会重置对象的Thread ID

撤销偏向锁阈值超过20次后,jvm 会这样觉得,我是不是偏向错了呢,于是会在给这些对象加锁时重新偏向至加锁线程

批量撤销

撤销偏向锁阈值超过40次后, jvm 会这样觉得,自己确实偏向错了,根本就不该偏向。于是整个类的所有对象都会变为不可偏向的,新建的对象也是不可偏向的。

锁消除

JVM中的同步省略:如果一个对象被发现只能从一个线程被访问到,那么对于这个对象的操作可以不考虑同步。


 


 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值