synchronized锁

参考于黑马的视频和文档

对象头格式

在这里插入图片描述

请添加图片描述

重量级锁

Thread2进入到临界区中的时候,会把object的对象头中的MarkWord设置为指向Monitor对象的指针

  • 开始的时候Monitor的owner为null
  • Thread2执行到临界区的时候,就会会把Monitor的owner设置为Thread2,Monitor只能有一个owner
  • Thread2上锁的过程中,如果Thread2和Thread3也进入到临界区执行,就会进入EntryList中阻塞(BLOCKING)

注意:

  • 轻量级锁的时候,obj原来的markword存储在lock Record中
  • 重量级锁的时候,原markword则存储在monitor对象中

上锁和解锁

在这里插入图片描述

在这里插入图片描述

  • 如果遇到异常:
    字节码里面有一个exception table异常表,里面会存储监控的范围,如果遇到异常,会跳到19行(如图所示)先把异常对象存储起来,然后进行解锁操作,再把异常抛出。

轻量级锁和锁膨胀

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

  • 需要注意:此时

  • record保存的是hashcode数据;

  • object原来的markword则保存的是指向record的指针+锁标志位

  • 00轻量级锁定状态,01是可偏向/偏向锁状态
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

锁自旋

在这里插入图片描述
自旋失败:在这里插入图片描述

注意:

  • 自旋默认是10次,可以使用-XX:PreBlockSpin更改自旋次数
  • JDK6之后是自适应自旋,如果自旋成功,那下次获取锁会多自旋几次;相反,如果自旋很少成功获得锁,那么可能下次直接省略自旋的过程,避免浪费处理器资源。

偏向锁

偏向锁是对轻量级锁的优化

当只有一个线程的时候,轻量级锁每次重入锁的时候都会生成一个新的LockRecord空间,然后进行CAS操作替换MarkWord,最后为null,然后继续执行。(参考上面),这样会影响性能

如何实现

Java 6 中引入了偏向锁来做进一步优化:只有第一次使用 CAS 将线程 ID 设置到对象的 Mark Word 头,之后发现
这个线程 ID 是自己的就表示没有竞争,不用重新 CAS。以后只要不发生竞争,这个对象就归该线程所有

一个对象创建时:

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

细心的读者看到这里可能会发现一个问题:当对象进人偏向状态的时候,Mark Word大部分的空间(23个比特)都用于存储持有锁的线程ID了,这部分空间占用了原有存储对象哈希码的位置,那原来对象的哈希码怎么办呢?

在Java 语言里面一个对象如果计算过哈希码,就应该一直保持该值不变(强烈推荐但不强制,因为用户可以重载 hashCode0 方法按自己的意愿返回哈希码),否则很多依赖对象哈希码的 API都可能存在出错风险。而作为绝大多数对象哈希码来源的 Object::hashCodeo方法,返回的是对象的一致性哈希码(Identity Fash Code),这个值是能强制保证不变的,它通过在对象头中存储计算结果来保证第一次计算之后,再次调用该方法取到的哈希码值永远不会再发生改变。因此,当一个对象已经计算过一致性哈希码后,它就再也无法进入偏向锁状态了;而当一个对象当前正处于偏向锁状态,又收到需要计算其一致性哈希码请求时,它的偏向状态会被立即撤销,并且锁会膨账为重量级锁。在重量级锁的实现中,对象头指向了重量级锁的位置,代表重量级锁的 ObjectMonitor 类里有字段可以记录非加锁状态(标志位为“01”)下的Mark Word,其中自然可以存储原来的哈希码。

偏向锁可以提高带有同步但无竞争的程序性能,但它同样是一个带有效益权衡 (Trade Off)性质的优化,也就是说它并非总是对程序运行有利。如果程序中大多数的锁都总是被多个不同的线程访问,那偏向模式就是多余的。在具体问题具体分析的前提下,有时候使用参数-XX:UseBiasedLocking来禁止偏向锁优化反而可以提升性能。

偏向锁撤销

  1. 会在调用hashcode的时候撤销
    在这里插入图片描述

  2. 竞争时撤销,并且锁升级在这里插入图片描述

锁消除

参考地址

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值