锁的状态
作者:互联网
锁的状态总共有四种:无锁状态、偏向锁、轻量级锁和重量级锁。随着锁的竞争,锁可以从偏向锁升级到轻量级锁,再升级的重量级锁。JDK 1.6中默认是开启偏向锁和轻量级锁的,我们也可以通过-XX:-UseBiasedLocking来禁用偏向锁。锁的状态保存在对象的头文件中,以32位的JDK为例。 每个对象一开始都是无锁的,随着线程间争夺锁,越激烈,锁的级别越高,并且锁只能升级不能降级。 锁的升级过程
- 对象在刚创建时为无锁状态
- 当有一个线程使用这个对象的时候,此时升级为偏向锁,在对象头中标记为偏向锁,当下次这个线程再次访问这个对象时,直接使用;
- 当有两个线程竞争这个对象的时候,此时锁从偏向锁升级为轻量级锁
- 当有更多的线程竞争这个对象的时候,此时轻量级锁升级为重量级锁
偏向锁,顾名思义,它会偏向于第一个访问锁的线程,如果在运行过程中,同步锁只有一个线程访问,不存在多线程争用的情况,则线程是不需要触发同步的,减少加锁/解锁的一些CAS操作(比如等待队列的一些CAS操作),这种情况下,就会给线程加一个偏向锁。 如果在运行过程中,遇到了其他线程抢占锁,则持有偏向锁的线程会被挂起,JVM会消除它身上的偏向锁,将锁恢复到标准的轻量级锁 引入偏向锁是为了在无多线程竞争的情况下尽量减少不必要的轻量级锁执行路径,因为轻量级锁的获取及释放依赖多次CAS原子指令,而偏向锁只需要在置换ThreadID的时候依赖一次CAS原子指令(由于一旦出现多线程竞争的情况就必须撤销偏向锁,所以偏向锁的撤销操作的性能损耗必须小于节省下来的CAS原子指令的性能消耗)。上面说过,轻量级锁是为了在线程交替执行同步块时提高性能,而偏向锁则是在只有一个线程执行同步块时进一步提高性能。 轻量级锁 轻量级锁是由偏向所升级来的,偏向锁运行在一个线程进入同步块的情况下,当第二个线程加入锁争用的时候,偏向锁就会升级为轻量级锁;
轻量级锁在没有竞争时(就自已这个线程),每次重入仍然需要执行CAS操作。Java6中引入了偏向锁来做进一步优化:只有每一次使用CAS将线程ID设置到对象的MarkWord头,之后发现这个线程ID是自已的就表示没有竞争,不用重新CAS
- 撤销偏向需要将持锁线程升级为轻量级锁,这个过程中所有线程需要STW
- 访问对象的hashCode也会撤销偏向锁
- 如果对象虽然被多个线程访问,但没有竞争,这时偏向了线程T1的对象仍有机会重新偏向T2,重偏向会重置对象的ThreadID
- 撤销偏向和生偏向都是批量进行的,以类为单为
- 如果撤销偏向到达某个阀值,整个类的所有对象都会变为不可偏向的
- 可以主动使用 -XX:-UseBiasedLocking 禁用偏向锁
偏向锁、轻量级锁、重量级锁之间的对比:
标签:状态,对象,CAS,线程,偏向,重量级,轻量级 来源: https://www.cnblogs.com/caoxb/p/13139091.html