龙空技术网

「浅谈Java」五,synchronized中锁的获取和释放

站在庭院看飘雨 76

前言:

此刻小伙伴们对“java程序停止锁没释放”大致比较关注,同学们都需要了解一些“java程序停止锁没释放”的相关资讯。那么小编也在网络上汇集了一些有关“java程序停止锁没释放””的相关知识,希望咱们能喜欢,看官们快快来了解一下吧!

【浅谈Java】主要针对Java开发技术知识的讲解。不会大而全详细讲解某一技术知识,只在短暂无事的时刻让你学习或温习Java知识体系中的一叶飘零。

相关文档传送门:

「浅谈Java」三,关键字synchronized同步机制-基础篇

「浅淡Java」四,synchronized的锁优化和升级

一,锁的获取

偏向锁获取过程

1,访问Mark Word中偏向锁的标识是否设置成1,锁标志位是否为01,确认为可偏向状态;

2,如果为可偏向状态,则测试线程ID是否指向当前线程,如果是,进入步骤5,否则进入步骤3;

3,如果线程ID并未指向当前线程,则通过CAS操作竞争锁。如果竞争成功,则将Mark Word中线程ID设置为当前线程ID,然后执行5;如果竞争失败,执行4;

4,如果CAS获取偏向锁失败,则表示有竞争。当到达全局安全点(safepoint)时获得偏向锁的线程被挂起,偏向锁升级为轻量级锁,然后被阻塞在安全点的线程继续往下执行同步代码。(撤销偏向锁的时候会导致stop the word);

5,执行同步代码;

轻量级锁获取过程

1,当有另外一个线程竞争锁时,由于该锁处于偏向锁状态,查验对象头Mark Word中的线程ID是不是自己的线程ID,执行下面2和3;

2,如果不是,该线程就会执行CAS操作获取锁。如果获取成功,直接替换Mark Word中的线程ID为自己的线程ID,该锁会保持偏向锁状态。如果获取失败,说明当前锁有一定的竞争,将偏向锁升级为轻量级锁;

3,如果升级轻量级锁,虚拟机首先将在当前线程的栈帧中建立一个名为锁记录(Lock Record)的空间,用于存储锁对象目前的Mark Word的拷贝,官方称之为 Displaced Mark Word;

4,拷贝对象头中的Mark Word复制到锁记录中,其它线程将会使用CAS操作尝试将对象的Mark Word更新为指向Lock Record的指针,并将Lock record里的owner指针指向object mark word。如果更新成功,则执行步骤4,否则执行步骤5。

4,如果这个更新动作成功了,那么这个线程就拥有了该对象的锁,并且对象Mark Word的锁标志位设置为“00”,即表示此对象处于轻量级锁定状态,

5,如果这个更新操作失败了,虚拟机首先会检查对象的Mark Word是否指向当前线程的栈帧,如果是则说明当前线程已经拥有了这个对象的锁,可以直接进入同步块继续执行。否则说明多个线程竞争锁,轻量级锁就要膨胀为重量级锁,锁标志的状态值变为“10”,Mark Word中存储的就是指向重量级锁(互斥量)的指针,后面等待锁的线程也要进入阻塞状态。

而当前线程便开始尝试使用自旋来获取锁,若失败则进入阻塞队列,成功进入同步执行。

重量级锁获取过程

1,如果有线程超过一定次数的重试还是获取不到锁,Mark Word立即将轻量级锁标记为重量级锁,此后所有获取不到锁的线程将被阻塞。参考“轻量级锁获取过程”第5条。

二,锁的释放

偏向锁的释放

偏向锁只有遇到其他线程尝试竞争偏向锁时,持有偏向锁的线程才会释放锁,线程不会主动去释放偏向锁。偏向锁的撤销,需要等待全局安全点(在这个时间点上没有字节码正在执行),它会首先暂停拥有偏向锁的线程,判断锁对象是否处于被锁定状态,撤销偏向锁后恢复到未锁定(标志位为“01”)或升级到轻量级锁(标志位为“00”)的状态。

轻量级锁的释放

由轻量锁切换到重量锁,是发生在轻量锁释放锁的期间,之前在获取锁的时候它拷贝了锁对象头的markword,在释放锁的时候如果它发现在它持有锁的期间有其他线程来尝试获取锁了,并且该线程对markword做了修改,两者比对发现不一致,则切换到重量锁。

等待轻量锁的线程不会阻塞,它会一直自旋等待锁,并如上所说修改markword

重量级锁的释放

当线程执行完功能的时候,锁会释放,如果有其它线程被阻塞中,会被唤醒开始非公平的锁竞争。成功获取锁时的线程会修改markword中monitor的指针数据。

当然线程执行完没有其它线程来获取对象锁,对象锁会释放变成无锁状态,相对应的对象头的markword数据也会同步变更。

【浅谈Java】本篇为synchronized的后续,主要对上篇文章的补充说明。感谢阅读,求关注。随手点赞,留有余香。学习是冰冻三尺非一日之寒,愿与诸君共勉励。

标签: #java程序停止锁没释放