Java 锁机制

版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/puzimengya/article/details/81146930

当没有竞争的时候,系统会默认使用偏斜锁。JVM 利用CAS(compare and swap)在 对象头的第一部分(mark word)设置 偏向线程ID,表示对象偏向于这个线程。 因为大部分并发场景下面 对象 生命周期 中最多被一个线程锁定, 使用偏斜锁的话可以降低 低竞争状态下的 额外开销。

这个时候如果有另外的线程试图锁定已经被倾斜过的对象,JVM会撤销(revoke)偏斜锁, 并切换到轻量级锁。 这时候轻量级锁 会根据 CAS 操作 Mark word 来试图 获取锁,如果成功就 切换为轻量级锁;否则 进一步 升级 为重量级锁。

 

自旋锁: 是竞争失败的线程,并不会真实的在操作系统层面挂起等待,而是JVM会让线程做几次空循环(For (;;)),循环几轮后,如果可以获得锁,那么进入临界区,如果还是不能获得锁的话,这时候才会在操作系统挂起等待。 一般在 低竞争并且占用锁的时间短的线程很实用。是一种在悲观锁中的乐观优化(因为JVM的synchronized是一种悲观锁 )。

 

死锁: 因为悲观锁独占CPU的特性,死锁就是线程A在持有锁A的情况下,试图进入锁B; 而线程B 在持有 锁B的情况下,试图进入锁A。如下图:

例如多个嵌套的 synchronized 有可能会发生死锁的情况。 所以为了避免死锁, 我们就需要 注意锁的获取顺序。 或者使用Object.wait() 或者  CountDownLatch.await()等带超时的方法。在长时间没有锁的情况下,即退出逻辑。

另外如果发生死锁的情况下可以使用jstack等工具去获取死锁发生的位置,这里就不过多阐述。

展开阅读全文

没有更多推荐了,返回首页