
因此, 对象产生以后, 头上就是红框里面这个样子,就是 线程ID没有
顺利 无竞争
首次
有线程试图获得这个对象的锁的时候
使用CAS操作把获取到这个锁的线程的ID记录在对象的MarkWord之中, 就是把绿框内的写进去
解锁

解锁的时候,什么都不要干
下次
这个线程再要得到这个对象的锁, 看到自己这个线程ID已经在里面写着了 ,
虚拟机都可以不再进行任何同步操作(例如加锁、解锁及对Mark Word的更新操作等)
这就是偏向, 得到过的 再得 就可以省了任何动作
竞争
其他线程 也试图得到这个锁, 试图把自己的线程ID写上去, 发现已经有一个线程ID了, 就会撤离偏向,要阻塞到安全点, 检查写这线程ID的线程是否解锁了
如果虽然有写着线程ID, 但是那个线程实际上已经从临界区出去了, 已经解锁了,
那么就撤销偏向, 变成未锁定的头

如果还在锁着,变成 轻量级锁

Hash

可以看到, 可偏向的状态下, 对象是没有地方放hash值的
在Java语言里面一个对象如果计算过哈希码,就应该一直保持该值不变(强烈推荐但不强制,因为用户可以重载hashCode()方法按自己的意愿返回哈希码)
而作为绝大多数对象哈希码来源的Object::hashCode()方法,返回的是对象的一致性哈希码(Identity Hash Code),这个值是能强制保证不变的,它通过在对象头中存储计算结果来保证第一次计算之后,再次调用该方法取到的哈希码值永远不会再发生改变。
因此, 在计算过hash以后, 这个对象 就不能变成 可偏向 了
当一个对象当前正处于偏向锁状态,又收到需要计算其一致性哈希码请求,它的偏向状态会被立即撤销, 并且会变成 重量级锁

代表重量级锁的ObjectMonitor类,可以存储原来的哈希码
网友评论