在 Java 中,synchronized
的实现涉及到几种不同的锁状态,包括无锁状态、偏向锁、轻量级锁和重量级锁。这些状态之间的转换是根据运行时的并发情况动态调整的。
对于轻量级锁来说,它并不直接涉及自旋的概念。轻量级锁主要通过比较并交换(CAS, Compare-And-Swap)操作来尝试原子地获取锁。
如果当前线程能够成功使用 CAS 操作将对象头中的 Mark Word 更新为指向自己线程栈帧中创建的锁记录(Lock Record),那么该线程就获得了这个锁;否则,表示存在竞争,轻量级锁会膨胀成重量级锁。
然而,与轻量级锁相关的“自旋”概念通常出现在重量级锁的上下文中,这被称为自适应自旋(Adaptive Spinning)。
当一个线程尝试获取已经被其他线程持有的重量级锁时,JVM 可能会让该线程进行短暂的自旋等待(即不断尝试获取锁而不立即进入阻塞状态),以期望持有锁的线程很快释放锁。
这种机制可以减少线程切换的开销,在锁被短时间占用的情况下特别有效。
自适应意味着 JVM 会根据历史数据自动调整每个锁对象的自旋次数,比如上次自旋是否成功获得锁等信息。
因此,总结来说:
- 轻量级锁:不直接涉及自旋,而是依赖于 CAS 操作来尝试非阻塞地获取锁。
- 重量级锁:可能会采用自适应自旋策略,允许尝试获取锁的线程在一定条件下自旋等待而不是立刻阻塞。
理解这两者的区别有助于更好地利用 synchronized
关键字提供的同步机制,并根据具体的应用场景选择合适的并发控制策略。
THE END