偏向锁的两次竞争

使用 synchronized() 时,括号中的对象就是我们所谓的 锁

其实真正的 锁 的信息,存在与括号中对象的对象头中

对象头的组成:

内容 说明
Mark Word 存储对象的 Hashcode、锁信息、分代年龄
Class Metadata Address 存储对象类型数据的指针
Array length 数组的长度(如果对象是数组的话)

主要看 MarkWord,它存放了锁信息,我们简化一下 MarkWord 存放的数据,仅拿出我们需要的:线程ID、偏向锁标志

偏向锁标志只有两个值:0和1,它用来表示当前是不是偏向锁

线程如何判断自己是否拿到偏向锁

线程读取一下锁对象头的 MarkWord 里的 线程ID 是不是自己的线程ID,如果是就是拿到了,不是就没拿到

偏向锁的两次竞争

两次竞争偏向锁

如果线程想竞争偏向锁,他会先向上面一样判断自己有没有拿到偏向锁,如果没有就会开始竞争偏向锁

第一次竞争

线程会先读取偏向锁标记,如果是 0,就会用 CAS 尝试将 0 变成 1,所以 偏向锁标记 的值可以表示:是否有线程在第一次竞争中胜利了

但其实这一步谁胜利了无所谓,关键在于第二次竞争

为什么要有第一次竞争

第一次竞争谁赢都无所谓,目的主要是为了:让 偏向锁标记 变为 1,也就是说,是为了把这个普通的对象,标记成一个偏向锁对象,所以其实第一次竞争我认为不能称之为竞争

第二次竞争

当线程读取偏向锁标记为 1 时,就会使用 CAS 来竞争,尝试将锁对象头中 MarkWord 存放的 线程ID 指向自己的线程。哪个成功指向自己,哪个线程就获得了偏向锁