synchronized 锁升级过程
Java中的synchronized锁升级过程是JVM为了提高并发性能而引入的一种优化策略,它在JDK 1.6及更高版本中得到了显著的改进。以下是synchronized锁从无锁状态到偏向锁、轻量级锁直至重量级锁的详细升级过程:
无锁状态:
当没有线程对对象进行同步操作时,对象处于无锁状态。
偏向锁(Biased Locking):
第一次获取锁时,如果对象尚未被任何线程锁定过,那么该线程会通过CAS操作尝试将对象头的标记设置为偏向模式,并记录当前线程ID。
在后续执行过程中,持有偏向锁的线程在进入同步块时无需再进行任何同步操作,直接认为自己拥有该锁,从而减少了锁竞争开销。
当有其他线程试图获取锁时,若发现偏向锁,则需要撤销偏向锁,将其升级至轻量级锁或重量级锁。
轻量级锁(Lightweight Locking):
如果对象已经带有偏向锁,但在多线程环境下出现了锁竞争,或者系统检测到偏向锁不再有效,会撤销偏向锁并尝试获取轻量级锁。
轻量级锁基于自旋锁原理实现,在加锁阶段,当前线程会在循环内尝试使用CAS操作将自己的栈上锁记录替换为对象头的锁记录地址,成功则获得锁,失败则表示存在锁竞争。
若轻量级锁自旋一段时间后仍无法获取锁(例如:自旋次数达到阈值),那么JVM会放弃轻量级锁机制,将锁升级为重量级锁。
重量级锁(Heavyweight Locking):
当轻量级锁升级为重量级锁时,线程将请求操作系统提供的互斥量(mutex),并将对象头转变为指向互斥量或monitor的指针,此时锁变为互斥锁。
获取重量级锁的线程会阻塞等待,直到获得锁的所有权,这样可以保证线程间的互斥性,但同时也带来了上下文切换等较高成本。
总结来说,锁升级的过程是为了尽可能地减少不必要的同步开销,当线程竞争不激烈时,尽量使用偏向锁和轻量级锁来提高程序运行效率;当竞争加剧时,才退化为重量级锁以确保数据安全。这种动态调整锁级别的策略使得Java在并发场景下能够兼顾性能与安全性。