轻量级锁

锁优化的过程:无锁->偏向锁->轻量级锁->重量级锁

假设许多存在数据竞争的情形都是一个线程执行完同步代码后,另外一个线程才开始竞争锁;

问题1 如何获取轻量级锁?
没有引入偏向锁的情形
当线程T1请求对象锁,即JVM执行monitorenter字节码指令时,

如果最初对象锁处于无锁状态unlocked,即共享对象头mark wordtag bits值为01,偏向模式标记位是0
首先,在线程T1的私有栈中分配lock record
此时,lock record由两部分组成:displaced hdrowner

然后复制共享对象头此时的mark record值到lock recorddisplaced hdr,使得owner指针指向共享对象的内存地址;

接着,尝试使用CAS设置共享对象头mark word指向线程T1的lock record
此时必操作成功,因为此时只有线程T1在请求锁,则设置共享对象头mark wordtag bits值为00,线程T1获得轻量级锁,开始执行同步代码;

当T1执行完同步代码,执行monitorexit释放锁时,尝试使用CAS操作设置共享对象头mark word指向线程T1的lock record

如果成功,则说明并没有其他线程来竞争对象锁,对象锁仍处于轻量级状态lightweight locked

如果失败,则说明在线程T1还持有轻量级锁时,有其他线程在竞争对象锁,然后才去一种比较慢的合理方式释放T1持有的轻量级锁,同时通知处于等待的线程去竞争获取锁。

如果共享对象处于轻量级锁状态lightweight locked,即共享对象头mark wordtag bits值为00,即有线程T1已经获得轻量级锁,在执行同步代码,现在线程T2也开始请求对象锁了,则线程T2尝试使用CAS竞争设置共享对象头mark word指向线程T2的lock record
如果失败,则表明线程T1还持有锁,还在临界区域内,就将轻量级锁膨胀为重量级锁;
如果成功,则表示线程T1已经释放锁了,退出临界区域了,否则可能出现两个线程同时进入临界区域,不满足锁的排他性;线程T2开始执行同步代码;

问题2:轻量级锁是如何处理锁重入情形的?
首先,判断对象锁是否处于轻量级状态;如果是,则接着判断对象头mark word 记录的lock record 是否指向当前线程的;如果是,则在前述lock record中压入一个0值。这样是为了方便重入轻量级锁的释放,因为当释放轻量级锁时,如果对象头mark word指向的地址记录一个0值,就可以知道是重入轻量级锁释放锁了,直接释放,不需要更新对象头mark word。这里也是sun公司的hotspot提供的不同于其他虚拟机的轻量级锁优化。

问题3:轻量级锁如何升级为重量级锁?

你可能感兴趣的:(轻量级锁)