Java中Synchronized的偏向锁是如何升级为轻量级锁的?
在Java中,synchronized关键字可以用于实现线程的同步。当一个线程获得了一个对象的锁时,其他线程需要等待该锁的释放才能继续执行。为了提高性能,Java引入了偏向锁和轻量级锁。
偏向锁适用于只有一个线程访问同步块的场景。当一个线程获得了对象的锁后,会在对象头中的Mark Word中记录下自己的ThreadID。此后,如果该线程再次请求该对象的锁,JVM会直接判断该线程是否为偏向锁的拥有者,如果是,则无需进行任何同步操作,直接进入同步块执行。这样可以减少不必要的锁竞争,提高性能。
当另一个线程请求该对象的锁时,会发生偏向锁的撤销。撤销的过程如下:
- 撤销偏向锁的线程会检查该线程是否执行过同步块,如果没有执行过,则恢复到无锁状态。
- 如果执行过同步块,会先判断偏向锁的拥有者是否还活着。如果还活着,则将对象头中的Mark Word更新为无锁状态,不再使用偏向锁。
- 如果偏向锁的拥有者已经死亡,则将对象头中的Mark Word更新为无锁状态,并唤醒其他等待该锁的线程。
当多个线程竞争同一个锁时,偏向锁会升级为轻量级锁。轻量级锁使用CAS(Compare And Swap)操作来实现。升级的过程如下:
- 当第二个线程尝试获取锁时,会尝试使用CAS操作将对象头中的Mark Word替换为指向锁记录的指针。如果成功,该线程获得了轻量级锁,可以继续执行同步块。
- 如果CAS操作失败,表示有其他线程竞争锁,此时会发生自旋(Spin)。
- 自旋期间,线程会一直尝试使用CAS操作获取锁,如果自旋结束后仍然没有获取到锁,线程会升级为重量级锁,进入阻塞状态。
总结来说,偏向锁适用于只有一个线程访问同步块的场景,可以减少不必要的锁竞争;而轻量级锁适用于有多个线程竞争同一个锁的场景,使用CAS操作来实现锁的获取和释放
原文地址: http://www.cveoy.top/t/topic/iIwH 著作权归作者所有。请勿转载和采集!