在Java中,synchronized
关键字是实现线程同步的一种方式,它涉及到锁的升级和释放的过程。理解synchronized
锁的升级可以分为三个阶段:无锁状态、偏向锁状态和轻量级锁状态。
-
无锁状态:
- 当对象被创建时,默认处于无锁状态。
- 多个线程可以同时访问对象的方法,不会进行同步操作,因此不存在锁竞争。
-
偏向锁状态:
- 当某个线程第一次访问一个
synchronized
方法或代码块时,Java 虚拟机会在对象头中的标记字段中记录当前线程的标识符。 - 如果以后没有其他线程来竞争锁,则该线程可以在进入和退出同步块时,不需要进行CAS操作来加锁和解锁,从而节省了操作时间。
- 当某个线程第一次访问一个
-
轻量级锁状态:
- 当存在多个线程访问同步块时,偏向锁会升级为轻量级锁。
- Java 虚拟机通过CAS操作尝试获取锁,如果成功则将对象头中的标记字段改为指向锁记录的指针,此时其他线程访问同步块时会进行自旋等待。
- 如果自旋等待成功,线程就可以进入同步块,如果自旋等待失败,表示存在竞争,轻量级锁会膨胀为重量级锁。
-
重量级锁状态:
- 如果自旋等待不成功,轻量级锁就会膨胀为重量级锁。
- 这时候锁的状态会被升级为重量级锁,重量级锁是通过操作系统的互斥量实现的,会导致线程进入阻塞状态,性能较差。
synchronized
锁在运行时会根据竞争的情况逐步升级锁的状态,从无锁到偏向锁再到轻量级锁,最后才是重量级锁。这种锁升级的过程是为了在保证数据安全的前提下,尽量减少锁带来的性能开销。