Java锁的四种状态及锁升级过程

锁的四种状态

Java锁的四种状态就是Synchronized的升级过程

  1. 刚new出来没有锁的状态
  2. 偏向锁
  3. 轻量级锁
  4. 重量级锁

刚new出来没有锁的状态

也有人称为无锁状态,但是要慎用。

无锁原来的意思是没有重量级锁,偏向锁,CAS都被称为无锁。其实都是概念上的问题,没必要纠结。

新new出来的对象布局,可看 Java对象布局 这篇文章

偏向锁

偏向锁严格来说不是一种锁。

不存在所竞争的过程,当第一个线程来了,这把锁就属于这个线程的,在这个线程持有这把锁的时候,有另一个线程来了,就会产生锁竞争的关系,于是就是进行锁升级,升级为轻量级锁,CAS。

为什么要有偏向锁?

如果一段代码百分七八十的时间都是一个线程在请求,每一次请求都会经过锁竞争的过程,这样会降低效率。如果有了偏向锁,就会减少锁竞争,可以提高效率。如果一旦出现了锁竞争,就会进行锁升级。

轻量级锁

偏向锁考虑的是有同步无竞争时程序的效率,而轻量级锁考虑的是竞争锁对象的线程不多,而且线程持有锁的时间也不长的情景。

什么时候偏向锁升级为轻量级锁?

当发生了锁竞争的时候,偏向锁就会升级为轻量级锁。

重量级锁

竞争锁的线程太多,就会被进入队列里,升级为重量级锁。

什么时候轻量级锁升级为重量级锁?

  1. 判断循环次数。
  2. 判断竞争锁的线程数。

锁对比

锁升级过程

Java中的锁有多种类型,主要包括无锁、偏向锁、轻量级锁和重量级锁。这些锁的升级过程如下:

  1. 无锁状态(Unlocked):当一个线程访问一个没有被锁定的对象时,它处于无锁状态。

  2. 偏向锁状态(Biased Locking):当一个线程获得了一个对象的锁,并且在后续的执行过程中没有其他线程竞争这个锁时,该锁会升级为偏向锁。偏向锁的目的是消除无竞争情况下的同步操作,提高性能。

  3. 轻量级锁状态(Lightweight Locking):如果一个线程尝试获取一个偏向锁失败,那么它会通过CAS(Compare and Swap)操作将对象头中的Mark Word 字段替换为指向锁记录的指针,并将锁记录的Owner字段设为当前线程ID。此时,该锁就升级为轻量级锁。轻量级锁使用自旋锁的形式,避免线程的上下文切换,提高性能。

  4. 重量级锁状态(Heavyweight Locking):轻量级锁升级为重量级锁是因为自旋操作未能成功。在多线程竞争激烈的情况下,为了保证数据的一致性和避免资源的浪费,JVM会将轻量级锁升级为重量级锁。重量级锁会让其他线程进入阻塞状态,并且使用操作系统的信号量机制来实现锁的互斥。

需要注意的是,锁的升级过程是动态的,根据竞争情况和线程执行的状态进行相应的调整。这种锁的升级过程可以提高并发性能,在无竞争情况下减少不必要的同步开销,但在竞争激烈的情况下可能会影响性能。因此,在使用锁时需要根据具体场景和需求合理选择适当的锁类型。

参考文章

  1. https://www.cnblogs.com/mingyueyy/p/13054296.html
  2. https://www.cnblogs.com/wzj4858/p/8215369.html

-------------本文结束感谢您的阅读-------------