在 Java 中,synchronized 锁可以进行升级,以提高锁的效率。具体来说,当多个线程竞争同一个锁时,锁的状态会按照以下顺序进行升级:
- 无锁:没有其他线程竞争锁。
- 偏向锁:一段同步代码一直被同一个线程访问,该线程会自动进入偏向锁状态。再次访问同步代码时,不需要做任何的检查,直接执行,降低了获取锁的代价。
- 轻量级锁:当锁竞争逐渐激烈时,会升级为轻量级锁。
- 重量级锁:当锁竞争非常激烈时,会升级为重量级锁。
- 锁的升级是不可逆的,只能进行锁升级,而无法进行锁降级。通过这种方式,可以根据锁的竞争情况动态调整锁的级别,从而提高程序的并发性能。
无锁很好理解,就是指当前没有任何线程持有该锁。也就是说没有线程正在执行同步代码块或同步方法。
偏向锁的“偏”是偏心的偏。即该锁会偏向于第一个获取它的线程。一段很长的时间内都只被一个线程使用锁。
在第一次获得锁时,会有一个CAS操作,之后该线程再获取锁,只需要判断mark word中是否是自己的线程id即可,而不是开销相对较大的CAS命令。
线程加锁的时间是错开的(也就是没有竞争),可以使用轻量级锁来优化。轻量级锁修改了对象头的锁标志,相对重量级锁性能提升很多。每次修改都是CAS操作,保证原子性。
底层使用monitor实现,里面涉及到用户态和内核态的切换、进程的上下文切换,成本较高,性能比较低。