本文主要是介绍Java synchronized关键字的底层实现以及锁升级优化的原理【一万字】,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
介绍了synchronized关键字实现锁的底层原理以及JDK对于synchronized做出的锁升级优化!
文章目录
- 1 syncronized基础知识
- 1.1 Synchronized锁的特性
- 1.2 synchronized锁表现形式
- 1.3 Mark Word
- 1.4 Monitor
- 2 synchronized块的底层原理
- 3 synchronized方法的底层原理
- 4 synchronized的优化(升级)
- 4.1 偏向锁
- 4.1.1 偏向锁的获取
- 4.1.2 偏向锁的撤销(升级)
- 4.1.3 偏向锁的关闭
- 4.1.4 批量重偏向和批量撤销
- 4.1.4.1 批量重偏向
- 4.1.4.2 批量撤销
- 4.1.4.3 总结
- 4.2 轻量级锁
- 4.2.1 轻量级锁加锁
- 4.2.2 轻量级锁解锁
- 4.2.3 锁重入
- 4.3 重量级锁
- 4.3.1 Monitor详解
- 4.3.2 monitor获取和释放
- 4.3.3 对象信息存放在哪里
- 4.3.4 自旋锁与自适应自旋
- 4.4 总体过程和优缺点对比
1 syncronized基础知识
synchronized 块是Java 提供的一种原子性内置锁,Java中的每个对象都可以把它当作一个同步锁来使用,这些Java内置的使用者看不到的锁被称为内部锁,也叫作监视器锁。
线程的执行代码在进入synchronized 代码块前会自动获取内部锁,这时候其他线程访问该同步代码块时会被阻塞挂起。拿到内部锁的线程会在正常退出同步代码块或者抛出异常后或者在同步块内调用了该内置锁资源的wait 系列方法时释放该内置锁。内置锁是排它锁,也就是当一个线程获取这个锁后, 其他线程必须等待该线程释放锁后才能获取该锁。
另外,由于Java 中的线程是与操作系统的原生线程一一对应的,所以当阻塞一个线程时,需要从用户态切换到内核态执行阻塞操作,这是很耗时的操作,而synchronized 的使用就会导致上下文切换。
1.1 Synchronized锁的特性
- 原子性:确保线程互斥的访问同步代码,如同单线程环境,自然具有原子性。
- 可见性:保证共享变量的修改能够及时可见,其实是通过Java内存模型中的 “对一个变量unlock操作之前,必须要同步到主内存中;如果对一个变量进行lock操作,则将会清空工作内存中此变量的值,在执行引擎使用此变量前,需要重新从主内存中load操作或assign操作初始化变量值” 来保证的;
- 有序性:synchronized内的代码和外部的代码禁止排序,至于内部的代码,似乎不会禁止排序,但是由于是单线程的,根据Java代码单线程的有序性定义“不管怎么重排序,单线程的执行结果都不能改变”,所以没有任何影响!
1.2 synchronized锁表现形式
synchronized锁,具有三种表现形式:
- 对于普通同步方法,锁是当前实例对象this
- 对于静态同步方法,锁是当前类的Class的对象
- 对于同步方法块 为Syncronized括号的配置对象。
1.3 Mark Word
synchronized作为锁是和Java是对象头中的Mark Word密不可分的。Java对象头里的Mark Word里默认存储对象的HashCode、分代年龄和锁标记位。关于Java对象的构成,可以看这篇文章:Java中的对象内存布局、压缩指针、对象大小计算以及对象访问定位的详解。
在运行期间,Mark Word里存储的数据会随着锁标志位的变化而变化。32位JVM在不同状态下mark word的组成如下表:
状态 | Mark Word(32 bit) | ||||
无锁 | hash:25 | age:4 | biased_lock:1 | lock:2 | |
偏向锁 | thread Id:23 | epoch:2 | age:4 | biased_lock:1 | lock:2 |
轻量级锁 | Lock record address:30(指向栈中锁记录的指针) | lock:2 | |||
重量级锁 | Monitor address:30 (指向监视器对象/monitor的指针) | lock:2 | |||
GC标记 | 30,空,只在Mark Sweep GC中用到,其他时刻无效 | lock:2 |
在64位虚拟机下,Mark Word是64bit大小的,不同状态下mark word的组成如下表:
状态 | Mark Word(64 bit) | |||||
无锁 | unused:25 | hash:31 | unused:1 | age:4 | biased_lock:1 | lock:2 |
偏向锁 | thread Id:54 | epoch:2 | unused:1 | age:4 | biased_lock:1 | lock:2 |
轻量级锁 | Lock record address:62(指向获得锁的线程的栈中锁记录Lock record的指针) | lock:2 | ||||
重量级锁 | Monitor address:62 (指向锁对象关联的monitor对象的指针) | lock:2 | ||||
GC标记 | 62,空,只在Mark Sweep GC中用到,其他时刻无效 | lock:2 |
下面来解释各种存放的数据的含义:
unused:就是表示没有使用的区域,在64位虚拟机的对象头中会出现。
hash:对象的hashcode,如果对象没有重写hashcode()方法,那么通过System.identityHashCode()方法获取。采用延迟加载技术,不会主动计算,但是一旦生成了hashcode,JVM会将其记录在markword中;
age:4位的Java对象GC年龄。对象在Survivor区复制一次,年龄增加1。当对象达到设定的阈值时,将会晋升到老年代。默认情况下,并行GC的年龄阈值为15。最大值也是15。
biased_lock:1位的偏向锁标记,为1时表示对象启用偏向锁,为0时表示对象没有偏向锁。
lock:2位的锁状态标记位,其中无锁和偏向锁的锁标志位都是01,只是在前面的1 bit的biased_lock区分了这是无锁状态还是偏向锁状态。
lock和biased_lock共同表示对象处于什么状态:
biased_lock 偏向锁标识位 | lock 锁标识位 | 状态 |
0 | 01 | 未锁定 |
1 | 01 | 偏向锁 |
无 | 00 | 轻量级锁 |
无 | 10 | 重量级锁 |
无 | 11 | GC标记 |
thread Id:持有偏向锁的线程ID。
epoch:的偏向锁的时间戳。
Lock record address:轻量级锁状态下,指向获得锁的线程的栈中锁记录Lock record的指针。
Monitor address:重量级锁状态下,指向锁对象关联的monitor对象的指针。
从上面的内容可以看出来,“锁”这个东西,可能是个锁记录+对象头里的引用指针(判断线程是否拥有锁时将线程的锁记录地址和对象头里的指针地址比较),也可能是对象头里的线程ID(判断线程是否拥有锁时将线程的ID和对象头里存储的线程ID比较),也可能是对象头里的Monitor指针和Monitor对象(重量级锁)。
JDK1.6及之后synchronized锁可以分为偏向锁、轻量级锁、重量级锁,并且前两种锁和Monitor是没关系的,这当然得益于JDK1.6对synchronized的优化,因此,人们常说的synchronized底层是使用Monitor来实现的这句话是不准确的。
1.4 Monitor
什么是Monitor?
- Monitor是一种用来实现同步的工具,又称为对象监视器/管程。
- 与每个java对象相关联,即每个java对象都有一个Monitor与之对应
- Monitor是实现Sychronized(内置锁)的基础,是shcronized作为重量级锁使用的对象(这源于JDK1.6的优化)。
在重量级锁阶段,线程在获取锁的时候,实际上就是获得一个锁对象关联的监视器对象 (Monitor)的所有权,Monitor可以认为是一个同步对象,所有的Java对象是天生携带一个Monitor,因此任何对象都可以作为锁。多个线程访问同步代码块时,相当于去争抢对象监视器对象、修改对象中的锁标识。更多Monitor详解在重量级锁那部分。
2 synchronized块的底层原理
案例:
public class SyncBlock {static int i;public static void main(String[] args) {synchronized (SyncBlock.class) {i++;}}
}
使用javap -v反编译后得到字节码如下:
如果没有synchronized块,而是普通块:
public class NoSyncBlock {static int i;public static void main(String[] args) {{i++;}}
}
那么就不会产生monitor相关字节码:
从上面的字节码中可知同步语句块的实现使用的是monitorenter 和 monitorexit指令,其中monitorenter指令指向同步代码块的开始位置,monitorexit指令则指明同步代码块的结束位置。
当执行monitorenter指令时,当前线程将试图获取锁对象对应的Monitor的持有权,当锁对象的 Monitor的计数器为0,那线程可以成功取得 Monitor,并将计数器值设置为 1,取锁成功。
如果当前线程已经拥有锁对象的 Monitor的持有权,那它可以重入这个 Monitor (关于重入性稍后会分析),重入时计数器的值也会加 1。
倘若其他线程已经拥有Monitor的所有权,那当前线程将被阻塞,直到正在执行线程执行完毕,即monitorexit指令被执行,执行线程将尝试释放锁并设置Monitor的计数器值减一直到为0 ,其他线程将有机会持有 Monitor。
值得注意的是编译器将会确保无论方法通过何种方式完成,方法中调用过的每条 monitorenter 指令都有执行其对应 monitorexit 指令,而无论这个方法是正常结束还是异常结束。为了保证在方法异常完成时 monitorenter 和 monitorexit 指令依然可以正确配对执行,编译器会自动产生一个异常处理器表,这个异常处理器表声明可处理所有的异常,它的目的就是用来执行 monitorexit 指令。从字节码中也可以看出多了一个monitorexit指令,它就是异常结束时被执行的释放monitor 的指令。因此monitorenter 和 monitorexit指令并不是一对一的,可能是一对多的。
当然在JDK1.6及之后的JDK版本中,对上面这些步骤进行了优化升级,得到了更好的性能,上面的步骤只有重量级锁时才会使用到。
3 synchronized方法的底层原理
public class SyncMethod {static int i;public static void main(String[] args) {}synchronized void sync() {i++;}
}
方法级的同步是隐式,即无需通过字节码指令来控制的,它实现在方法调用和返回操作之中。JVM可以从方法常量池中的方法表结构(method_info Structure) 中的 ACC_SYNCHRONIZED
访问标志区分一个方法是否同步方法。
当方法调用时,调用指令将会 检查方法的 ACC_SYNCHRONIZED 访问标志是否被设置,如果设置了,执行线程将先持有monitor(虚拟机规范中用的是管程一词), 然后再执行方法,最后在方法完成(无论是正常完成还是非正常完成)时释放monitor。在方法执行期间,执行线程持有了monitor,其他任何线程都无法再获得同一个monitor。如果一个同步方法执行期间抛 出了异常,并且在方法内部无法处理此异常,那这个同步方法所持有的monitor将在异常抛到同步方法之外时自动释放。下面我们看看字节码层面如何实现:
从字节码中可以看出,synchronized修饰的方法并没有monitorenter指令和monitorexit指令,取得代之的确是ACC_SYNCHRONIZED标识,该标识指明了该方法是一个同步方法,JVM通过该ACC_SYNCHRONIZED访问标志来辨别一个方法是否声明为同步方法,从而执行相应的同步调用。
在JDK1.6之前的同步块和同步方法两个同步方式实际都是通过获取Monitor和释放Monitor来实现同步的,但在JDK1.6时,规则改变了,下面来看看JDK1.6的锁升级!
在JDK1.6之前的同步块和同步方法两个同步方式实际都是通过获取Monitor和释放Monitor来实现同步的,其实wait、notiy和notifyAll等方法也是依赖于Monitor对象的内部方法来完成的,这也就是为什么需要在同步方法或者同步代码块中调用的原因(需要先获取对象的锁,才能执行),否则会抛出java.lang.IllegalMonitorStateException的异常。
在JDK1.6之前,synchronized属于重量级锁,效率低下,因为Monitor是依赖于底层的操作系统的互斥原语mutex来实现,JDK1.6之前实际上加锁时会调用Monitor的enter方法,解锁时会调用Monitor的exit方法,由于java的线程是映射到操作系统的原生线程之上的,如果要操作Monitor对象,都需要操作系统来帮忙完成,这会导致线程在“用户态和内核态”两个态之间来回切换,这个状态之间的转换需要相对比较长的时间,对性能有较大影响。
庆幸的是在JDK1.6之后Java官方对从JVM层面对synchronized较大优化,所以现在的synchronized锁效率也优化得很不错了,JDK1.6之后,为了减少获得锁和释放锁所带来的性能消耗,为了减少这种重量级锁的使用,引入了轻量级锁和偏向锁,这两个锁可以不依赖Monitor的操作。
4 synchronized的优化(升级)
JDK1.6为了减少获得锁和释放锁带来的性能消耗,引入了“偏向锁”和“轻量级锁”,在JDK 1.6中,锁对象一共有4种状态,级别从低到高依次是:无锁状态、偏向锁状态、轻量级锁状态和重量级锁状态,这几个状态会随着竞争情况逐渐升级。
锁可以升级但不能降级,意味着偏向锁升级成轻量级锁后不能降级成偏向锁。这种锁升级却不能降级的策略,目的是为了提高获得锁和释放锁的效率,同时降低了实现复杂度。
4.1 偏向锁
HotSpot的作者经过研究发现,大多数情况下,锁不仅不存在多线程竞争,而且总是由同一线程多次获得,为了让线程获得锁的代价更低而引入了偏向锁。
偏向锁是在单线程执行代码块时使用的机制,如果在多线程并发的环境下(即线程A尚未执行完同步代码块,线程B发起了申请锁的申请),则一定会转化为轻量级锁或者重量级锁。
引入偏向锁主要目的是:为了在没有多线程竞争的情况下尽量减少不必要的轻量级锁执行路径。因为轻量级锁、重量级锁的加锁、解锁操作是需要依赖多次CAS原子指令的,而偏向锁只需要在置换ThreadID的时候依赖一次CAS原子指令(由于一旦出现多线程竞争的情况就必须撤销偏向锁,所以偏向锁的撤销操作的性能损耗也必须小于节省下来的CAS原子指令的性能消耗)。
4.1.1 偏向锁的获取
- 检测锁对象的MarkWord是否为可偏向状态,即是否为偏向锁标识1,锁标识位为01,如果是,则执行步骤(2);否则,直接表示锁对象的Mark Word为不可偏向状态(关闭了偏向锁),则直接构造轻量级锁,然后往下执行同步代码;
- 若为可偏向状态,则判断Mark Word中的线程ID是否为当前线程ID,如果是,表示线程A已经获得了这个偏向锁,虚拟机不再进行任何同步操作,不需要进行CAS操作来加锁和解锁,提高性能,相当于获取到了锁,然后往下执行同步代码;否则执行步骤(3);
- 如果Mark Word的线程ID不为当前线程ID,则通过CAS操作竞争:CAS(0,current_tid),这里的CAS默认预期线程ID为0,即还没有任何线程获得过锁。CAS成功之后,则将Mark Word的线程ID修改为当前线程ID,表示获取到了锁,然后往下执行同步代码;否则执行步骤(4);
- 如果CAS失败,证明当前锁对象的偏向锁已被其他线程获取了,存在多线程竞争情况,此时可能出现重偏向或者锁升级的步骤。
4.1.2 偏向锁的撤销(升级)
获取偏向锁的线程线程是不会主动去释放偏向锁,也就是即使最开始的线程执行完毕了同步的内容,其保存在Mark Word中的线程ID也不会替换回来,需要等待其他线程来竞争,才有可能被被动的替换。
如果有第二个线程来获取偏向锁,但是CAS失败了,此时就会执行锁撤销的操作,锁撤销操作也就是锁升级操作,对偏向锁进行撤销时,需要等待持有锁的线程到达全局安全点。当到达全局安全点(safepoint)时获得偏向锁的线程被挂起,然后有一下两种情况:
- 如果原获得偏向锁的线程如果已经退出了临界区,也就是同步代码块执行完了,不存在锁竞争,那么这个时候争抢锁的线程可以直接进行锁升级。锁标志位改为00,将指向当前线程的锁记录地址的指针放入对象头Mark Word。当前线程获得轻量级锁。
- 如果原获得偏向锁的线程的同步代码块还没执行完,处于临界区之内,这个时候会把锁标志位改为00,同时原获得偏向锁的线程的锁记录地址的指针放入对象头Mark Word,后唤醒持有锁的线程,进入轻量级锁的竞争模式,此处将当前线程挂起再恢复原持有锁线程的过程中并没有发生锁的转移,仍然在之前的线程手中,只是穿插了个“将对象头中的线程ID变更为指向锁记录地址的指针” 这么个事。
- 简单的说,将偏向线程栈中的所有Lock Record的Displaced Mark Word设置为null,再将最高位的Lock Record的Displaced Mark Word 设置为无锁状态,然后将对象头指向最高位的Lock Record。这里没有用到CAS指令,因为是在safepoint,可以直接升级成轻量级锁。
除了有第二个线程尝试获取锁时会导致偏向锁撤销(升级)之外,下列情况也会导致偏向锁撤销:
- 当调用锁对象的
Object#hash
或System.identityHashCode()
方法时,会导致该对象的偏向锁直接升级为重量级锁。这是因为在Java中一个对象的hashcode是在调用这两个方法时才生成的,如果是无锁状态则存放在mark word中,如果是轻量级锁则存放在对应的线程的Lock Record栈帧中,如果是重量级锁则存放在对应的monitor中,而偏向锁是没有地方能存放该信息的,所以必须升级。 - 另外,执行锁对象的
wait/notify/notifyall
方法,会将其恢复成无锁状态,直接膨胀成重量级锁。执行Unsafe类的monitorenter/trymonitorenter/monitorexit
方法,会将其恢复成无锁状态,直接膨胀成重量级锁。
4.1.3 偏向锁的关闭
偏向锁模式在JDK1.6之后是默认启用的,但是它在JVM应用程序启动几秒钟之后才激活(对象头从无锁模式转换为偏向锁模式),默认为4000ms,如有必要可以使用JVM参数来关闭延迟:-XX:BiasedLockingStartupDelay=0。因此,如果在JVM对象在转换为偏向模式之前对于无锁模式的对象加锁,即对于JVM启动前四秒的对象加锁,则直接进入轻量级锁加锁模式。
为什么会延迟初始化?因为预计在JVM时启动前几秒中存在大量同步操作,如果即时开启偏向锁,可能会出现大量的偏向锁撤销升级的操作,反而降低了程序的效率。
如果你确定应用程序里所有的锁通常情况下处于竞争状态,可以通过JVM参数关闭偏向锁:-XX:-UseBiasedLocking=false,那么程序默认会进入轻量级锁状态。
注意,在jdk15开始默认不开启偏向锁模式。所以锁,偏向锁很可能在未来直接被干掉了。
4.1.4 批量重偏向和批量撤销
4.1.4.1 批量重偏向
批量重偏向:当创建了大量同类型对象并且一个线程对它们执行了初始的同步操作,而后来其他的线程也来将这些对象作为锁对象进行同步操作,可能会导偏向锁重偏向。
通过BiasedLockingBulkRebiasThreshold
参数可以设置批量重偏向的阈值,默认为20
,当达到第19次撤销偏向
的时候,后续操作将会执行重偏向
操作,即此时锁不会升级为轻量级锁,它还是偏向锁,只是偏向线程id更新成了当前线程的id
。
如下案例,假设有一个锁对象类:
public class LockA {}
如下案例,我们为LockA创建30个锁实例,并且使用线程t1依次进行锁定,随后使用线程t2再依次进行锁定,我们借助jol打印此时锁对象的对象头信息,加入启动参数-XX:BiasedLockingStartupDelay=0来关闭偏向锁延迟:
public class BiasedLock {static Thread t1;static Thread t2;public static void main(String[] args) throws Exception {List<LockA> list = new ArrayList<>();t1 = new Thread(() -> {for (int i = 0; i < 30; i++) {LockA d = new LockA();list.add(d);synchronized (d) {System.out.println((i + "\t" + JolUtils.toPrintableSimple(d)));}}LockSupport.unpark(t2);}, "t1");t1.start();t2 = new Thread(() -> {LockSupport.park();System.out.println(("===============> "));for (int i = 0; i < 30; i++) {LockA d = list.get(i);System.out.println((i + "\tbefore" + "\t" + JolUtils.toPrintableSimple(d)));synchronized (d) {System.out.println((i + "\tcenter" + "\t" + JolUtils.toPrintableSimple(d)));}System.out.println((i + "\tafter" + "\t" + JolUtils.toPrintableSimple(d)));}}, "t2");t2.start();}
}
结果如下:
0 00000000 00000000 00000000 00000000 00100000 01001000 10001000 00000101
1 00000000 00000000 00000000 00000000 00100000 01001000 10001000 00000101
2 00000000 00000000 00000000 00000000 00100000 01001000 10001000 00000101
3 00000000 00000000 00000000 00000000 00100000 01001000 10001000 00000101
4 00000000 00000000 00000000 00000000 00100000 01001000 10001000 00000101
5 00000000 00000000 00000000 00000000 00100000 01001000 10001000 00000101
6 00000000 00000000 00000000 00000000 00100000 01001000 10001000 00000101
7 00000000 00000000 00000000 00000000 00100000 01001000 10001000 00000101
8 00000000 00000000 00000000 00000000 00100000 01001000 10001000 00000101
9 00000000 00000000 00000000 00000000 00100000 01001000 10001000 00000101
10 00000000 00000000 00000000 00000000 00100000 01001000 10001000 00000101
11 00000000 00000000 00000000 00000000 00100000 01001000 10001000 00000101
12 00000000 00000000 00000000 00000000 00100000 01001000 10001000 00000101
13 00000000 00000000 00000000 00000000 00100000 01001000 10001000 00000101
14 00000000 00000000 00000000 00000000 00100000 01001000 10001000 00000101
15 00000000 00000000 00000000 00000000 00100000 01001000 10001000 00000101
16 00000000 00000000 00000000 00000000 00100000 01001000 10001000 00000101
17 00000000 00000000 00000000 00000000 00100000 01001000 10001000 00000101
18 00000000 00000000 00000000 00000000 00100000 01001000 10001000 00000101
19 00000000 00000000 00000000 00000000 00100000 01001000 10001000 00000101
20 00000000 00000000 00000000 00000000 00100000 01001000 10001000 00000101
21 00000000 00000000 00000000 00000000 00100000 01001000 10001000 00000101
22 00000000 00000000 00000000 00000000 00100000 01001000 10001000 00000101
23 00000000 00000000 00000000 00000000 00100000 01001000 10001000 00000101
24 00000000 00000000 00000000 00000000 00100000 01001000 10001000 00000101
25 00000000 00000000 00000000 00000000 00100000 01001000 10001000 00000101
26 00000000 00000000 00000000 00000000 00100000 01001000 10001000 00000101
27 00000000 00000000 00000000 00000000 00100000 01001000 10001000 00000101
28 00000000 00000000 00000000 00000000 00100000 01001000 10001000 00000101
29 00000000 00000000 00000000 00000000 00100000 01001000 10001000 00000101
===============>
0 before 00000000 00000000 00000000 00000000 00100000 01001000 10001000 00000101
0 center 00000000 00000000 00000000 00000000 00100000 11001111 11110010 00000000
0 after 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
1 before 00000000 00000000 00000000 00000000 00100000 01001000 10001000 00000101
1 center 00000000 00000000 00000000 00000000 00100000 11001111 11110010 00000000
1 after 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
2 before 00000000 00000000 00000000 00000000 00100000 01001000 10001000 00000101
2 center 00000000 00000000 00000000 00000000 00100000 11001111 11110010 00000000
2 after 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
3 before 00000000 00000000 00000000 00000000 00100000 01001000 10001000 00000101
3 center 00000000 00000000 00000000 00000000 00100000 11001111 11110010 00000000
3 after 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
4 before 00000000 00000000 00000000 00000000 00100000 01001000 10001000 00000101
4 center 00000000 00000000 00000000 00000000 00100000 11001111 11110010 00000000
4 after 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
5 before 00000000 00000000 00000000 00000000 00100000 01001000 10001000 00000101
5 center 00000000 00000000 00000000 00000000 00100000 11001111 11110010 00000000
5 after 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
6 before 00000000 00000000 00000000 00000000 00100000 01001000 10001000 00000101
6 center 00000000 00000000 00000000 00000000 00100000 11001111 11110010 00000000
6 after 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
7 before 00000000 00000000 00000000 00000000 00100000 01001000 10001000 00000101
7 center 00000000 00000000 00000000 00000000 00100000 11001111 11110010 00000000
7 after 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
8 before 00000000 00000000 00000000 00000000 00100000 01001000 10001000 00000101
8 center 00000000 00000000 00000000 00000000 00100000 11001111 11110010 00000000
8 after 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
9 before 00000000 00000000 00000000 00000000 00100000 01001000 10001000 00000101
9 center 00000000 00000000 00000000 00000000 00100000 11001111 11110010 00000000
9 after 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
10 before 00000000 00000000 00000000 00000000 00100000 01001000 10001000 00000101
10 center 00000000 00000000 00000000 00000000 00100000 11001111 11110010 00000000
10 after 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
11 before 00000000 00000000 00000000 00000000 00100000 01001000 10001000 00000101
11 center 00000000 00000000 00000000 00000000 00100000 11001111 11110010 00000000
11 after 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
12 before 00000000 00000000 00000000 00000000 00100000 01001000 10001000 00000101
12 center 00000000 00000000 00000000 00000000 00100000 11001111 11110010 00000000
12 after 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
13 before 00000000 00000000 00000000 00000000 00100000 01001000 10001000 00000101
13 center 00000000 00000000 00000000 00000000 00100000 11001111 11110010 00000000
13 after 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
14 before 00000000 00000000 00000000 00000000 00100000 01001000 10001000 00000101
14 center 00000000 00000000 00000000 00000000 00100000 11001111 11110010 00000000
14 after 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
15 before 00000000 00000000 00000000 00000000 00100000 01001000 10001000 00000101
15 center 00000000 00000000 00000000 00000000 00100000 11001111 11110010 00000000
15 after 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
16 before 00000000 00000000 00000000 00000000 00100000 01001000 10001000 00000101
16 center 00000000 00000000 00000000 00000000 00100000 11001111 11110010 00000000
16 after 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
17 before 00000000 00000000 00000000 00000000 00100000 01001000 10001000 00000101
17 center 00000000 00000000 00000000 00000000 00100000 11001111 11110010 00000000
17 after 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
18 before 00000000 00000000 00000000 00000000 00100000 01001000 10001000 00000101
18 center 00000000 00000000 00000000 00000000 00100000 11001111 11110010 00000000
18 after 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
19 before 00000000 00000000 00000000 00000000 00100000 01001000 10001000 00000101
19 center 00000000 00000000 00000000 00000000 00100000 01001000 10101001 00000101
19 after 00000000 00000000 00000000 00000000 00100000 01001000 10101001 00000101
20 before 00000000 00000000 00000000 00000000 00100000 01001000 10001000 00000101
20 center 00000000 00000000 00000000 00000000 00100000 01001000 10101001 00000101
20 after 00000000 00000000 00000000 00000000 00100000 01001000 10101001 00000101
21 before 00000000 00000000 00000000 00000000 00100000 01001000 10001000 00000101
21 center 00000000 00000000 00000000 00000000 00100000 01001000 10101001 00000101
21 after 00000000 00000000 00000000 00000000 00100000 01001000 10101001 00000101
22 before 00000000 00000000 00000000 00000000 00100000 01001000 10001000 00000101
22 center 00000000 00000000 00000000 00000000 00100000 01001000 10101001 00000101
22 after 00000000 00000000 00000000 00000000 00100000 01001000 10101001 00000101
23 before 00000000 00000000 00000000 00000000 00100000 01001000 10001000 00000101
23 center 00000000 00000000 00000000 00000000 00100000 01001000 10101001 00000101
23 after 00000000 00000000 00000000 00000000 00100000 01001000 10101001 00000101
24 before 00000000 00000000 00000000 00000000 00100000 01001000 10001000 00000101
24 center 00000000 00000000 00000000 00000000 00100000 01001000 10101001 00000101
24 after 00000000 00000000 00000000 00000000 00100000 01001000 10101001 00000101
25 before 00000000 00000000 00000000 00000000 00100000 01001000 10001000 00000101
25 center 00000000 00000000 00000000 00000000 00100000 01001000 10101001 00000101
25 after 00000000 00000000 00000000 00000000 00100000 01001000 10101001 00000101
26 before 00000000 00000000 00000000 00000000 00100000 01001000 10001000 00000101
26 center 00000000 00000000 00000000 00000000 00100000 01001000 10101001 00000101
26 after 00000000 00000000 00000000 00000000 00100000 01001000 10101001 00000101
27 before 00000000 00000000 00000000 00000000 00100000 01001000 10001000 00000101
27 center 00000000 00000000 00000000 00000000 00100000 01001000 10101001 00000101
27 after 00000000 00000000 00000000 00000000 00100000 01001000 10101001 00000101
28 before 00000000 00000000 00000000 00000000 00100000 01001000 10001000 00000101
28 center 00000000 00000000 00000000 00000000 00100000 01001000 10101001 00000101
28 after 00000000 00000000 00000000 00000000 00100000 01001000 10101001 00000101
29 before 00000000 00000000 00000000 00000000 00100000 01001000 10001000 00000101
29 center 00000000 00000000 00000000 00000000 00100000 01001000 10101001 00000101
29 after 00000000 00000000 00000000 00000000 00100000 01001000 10101001 00000101
可以看到,在线程t1加锁之后,锁对象的Mark Word前面变成了当前线程的ID,此时是偏向锁,而在t2加锁之后,在第0-18个对象,即前19个对象之中,锁升级为了轻量级锁,锁标志位000,轻量级锁解锁之后变成了001,即不可偏向。
而从第20个对象开始,锁并没有升级,他还是偏向锁,只不过此时偏向线程id变成了线程t2,这就是批量重偏向。
注意:偏向锁重偏向一次之后不可再次重偏向,只能撤销升级为轻量级锁。
批量重偏向是针对一个类的对象,计数方式也是以类为单位的,假设有另外一个锁对象LockB:
public class LockB { }
我们将刚才的程序改为分别用15个LockA和LockB对象进行同步,加入启动参数-XX:BiasedLockingStartupDelay=0来关闭偏向锁延迟:
public class BiasedLock2 {static Thread t1;static Thread t2;public static void main(String[] args) throws Exception {List<Object> list = new ArrayList<>();t1 = new Thread(() -> {for (int i = 0; i < 30; i++) {if (i % 2 == 0) {LockA d = new LockA();list.add(d);synchronized (d) {System.out.println((i + "\t" + JolUtils.toPrintableSimple(d)));}} else {LockB d = new LockB();list.add(d);synchronized (d) {System.out.println((i + "\t" + JolUtils.toPrintableSimple(d)));}}}LockSupport.unpark(t2);}, "t1");t1.start();t2 = new Thread(() -> {LockSupport.park();System.out.println(("===============> "));for (int i = 0; i < 30; i++) {Object d = list.get(i);System.out.println((i + "\tbefore" + "\t" + JolUtils.toPrintableSimple(d)));synchronized (d) {System.out.println((i + "\tcenter" + "\t" + JolUtils.toPrintableSimple(d)));}System.out.println((i + "\tafter" + "\t" + JolUtils.toPrintableSimple(d)));}}, "t2");t2.start();}
}
测试结果如下:
0 00000000 00000000 00000000 00000000 00100000 01101111 11101111 11011000
1 00000000 00000000 00000000 00000000 00100000 01101111 11101111 11011000
2 00000000 00000000 00000000 00000000 00100000 01101111 11101111 11011000
3 00000000 00000000 00000000 00000000 00100000 01101111 11101111 11011000
4 00000000 00000000 00000000 00000000 00100000 01101111 11101111 11011000
5 00000000 00000000 00000000 00000000 00100000 01101111 11101111 11011000
6 00000000 00000000 00000000 00000000 00100000 01101111 11101111 11011000
7 00000000 00000000 00000000 00000000 00100000 01101111 11101111 11011000
8 00000000 00000000 00000000 00000000 00100000 01101111 11101111 11011000
9 00000000 00000000 00000000 00000000 00100000 01101111 11101111 11011000
10 00000000 00000000 00000000 00000000 00100000 01101111 11101111 11011000
11 00000000 00000000 00000000 00000000 00100000 01101111 11101111 11011000
12 00000000 00000000 00000000 00000000 00100000 01101111 11101111 11011000
13 00000000 00000000 00000000 00000000 00100000 01101111 11101111 11011000
14 00000000 00000000 00000000 00000000 00100000 01101111 11101111 11011000
15 00000000 00000000 00000000 00000000 00100000 01101111 11101111 11011000
16 00000000 00000000 00000000 00000000 00100000 01101111 11101111 11011000
17 00000000 00000000 00000000 00000000 00100000 01101111 11101111 11011000
18 00000000 00000000 00000000 00000000 00100000 01101111 11101111 11011000
19 00000000 00000000 00000000 00000000 00100000 01101111 11101111 11011000
20 00000000 00000000 00000000 00000000 00100000 01101111 11101111 11011000
21 00000000 00000000 00000000 00000000 00100000 01101111 11101111 11011000
22 00000000 00000000 00000000 00000000 00100000 01101111 11101111 11011000
23 00000000 00000000 00000000 00000000 00100000 01101111 11101111 11011000
24 00000000 00000000 00000000 00000000 00100000 01101111 11101111 11011000
25 00000000 00000000 00000000 00000000 00100000 01101111 11101111 11011000
26 00000000 00000000 00000000 00000000 00100000 01101111 11101111 11011000
27 00000000 00000000 00000000 00000000 00100000 01101111 11101111 11011000
28 00000000 00000000 00000000 00000000 00100000 01101111 11101111 11011000
29 00000000 00000000 00000000 00000000 00100000 01101111 11101111 11011000
===============>
0 before 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
0 center 00000000 00000000 00000000 00000000 00100000 01111111 11110100 11000000
0 after 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
1 before 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
1 center 00000000 00000000 00000000 00000000 00100000 01111111 11110100 11000000
1 after 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
2 before 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
2 center 00000000 00000000 00000000 00000000 00100000 01111111 11110100 11000000
2 after 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
3 before 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
3 center 00000000 00000000 00000000 00000000 00100000 01111111 11110100 11000000
3 after 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
4 before 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
4 center 00000000 00000000 00000000 00000000 00100000 01111111 11110100 11000000
4 after 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
5 before 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
5 center 00000000 00000000 00000000 00000000 00100000 01111111 11110100 11000000
5 after 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
6 before 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
6 center 00000000 00000000 00000000 00000000 00100000 01111111 11110100 11000000
6 after 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
7 before 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
7 center 00000000 00000000 00000000 00000000 00100000 01111111 11110100 11000000
7 after 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
8 before 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
8 center 00000000 00000000 00000000 00000000 00100000 01111111 11110100 11000000
8 after 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
9 before 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
9 center 00000000 00000000 00000000 00000000 00100000 01111111 11110100 11000000
9 after 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
10 before 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
10 center 00000000 00000000 00000000 00000000 00100000 01111111 11110100 11000000
10 after 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
11 before 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
11 center 00000000 00000000 00000000 00000000 00100000 01111111 11110100 11000000
11 after 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
12 before 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
12 center 00000000 00000000 00000000 00000000 00100000 01111111 11110100 11000000
12 after 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
13 before 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
13 center 00000000 00000000 00000000 00000000 00100000 01111111 11110100 11000000
13 after 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
14 before 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
14 center 00000000 00000000 00000000 00000000 00100000 01111111 11110100 11000000
14 after 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
15 before 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
15 center 00000000 00000000 00000000 00000000 00100000 01111111 11110100 11000000
15 after 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
16 before 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
16 center 00000000 00000000 00000000 00000000 00100000 01111111 11110100 11000000
16 after 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
17 before 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
17 center 00000000 00000000 00000000 00000000 00100000 01111111 11110100 11000000
17 after 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
18 before 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
18 center 00000000 00000000 00000000 00000000 00100000 01111111 11110100 11000000
18 after 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
19 before 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
19 center 00000000 00000000 00000000 00000000 00100000 01111111 11110100 11000000
19 after 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
20 before 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
20 center 00000000 00000000 00000000 00000000 00100000 01111111 11110100 11000000
20 after 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
21 before 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
21 center 00000000 00000000 00000000 00000000 00100000 01111111 11110100 11000000
21 after 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
22 before 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
22 center 00000000 00000000 00000000 00000000 00100000 01111111 11110100 11000000
22 after 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
23 before 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
23 center 00000000 00000000 00000000 00000000 00100000 01111111 11110100 11000000
23 after 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
24 before 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
24 center 00000000 00000000 00000000 00000000 00100000 01111111 11110100 11000000
24 after 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
25 before 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
25 center 00000000 00000000 00000000 00000000 00100000 01111111 11110100 11000000
25 after 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
26 before 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
26 center 00000000 00000000 00000000 00000000 00100000 01111111 11110100 11000000
26 after 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
27 before 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
27 center 00000000 00000000 00000000 00000000 00100000 01111111 11110100 11000000
27 after 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
28 before 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
28 center 00000000 00000000 00000000 00000000 00100000 01111111 11110100 11000000
28 after 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
29 before 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
29 center 00000000 00000000 00000000 00000000 00100000 01111111 11110100 11000000
29 after 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
可以看到,此时并没有出现批量重偏向的现象。
4.1.4.2 批量撤销
批量撤销:在多线程竞争剧烈的情况下,使用偏向锁将会降低效率,为了避免锁撤销操作,于是乎产生了批量撤销机制。
通过BiasedLockingBulkRevokeThreshold
参数可以设置批量撤销的阈值,默认为40
,当对同类的对象达到第39次锁撤销
的时候,后续操作将会执行批量撤销
操作,JVM会把这个对象所对应的类所有的对象的偏向锁都进行撤销;并且新实例化的对象也是不可偏向的
。
如下案例,加入启动参数-XX:BiasedLockingStartupDelay=0
来关闭偏向锁延迟并测试:
public class BiasedLock4 {static Thread t1;static Thread t2;static Thread t3;public static void main(String[] args) throws Exception {List<LockA> list = new ArrayList<>();t1 = new Thread(() -> {for (int i = 0; i < 50; i++) {LockA d = new LockA();list.add(d);synchronized (d) {System.out.println((i + "\t" + JolUtils.toPrintableSimple(d)));}}LockSupport.unpark(t2);}, "t1");t1.start();t2 = new Thread(() -> {LockSupport.park();System.out.println(("===============> "));for (int i = 0; i < 39; i++) {LockA d = list.get(i);System.out.println((i + "\tbefore" + "\t" + JolUtils.toPrintableSimple(d)));synchronized (d) {System.out.println((i + "\tcenter" + "\t" + JolUtils.toPrintableSimple(d)));}System.out.println((i + "\tafter" + "\t" + JolUtils.toPrintableSimple(d)));}LockSupport.unpark(t3);}, "t2");t2.start();t3 = new Thread(() -> {LockSupport.park();System.out.println(("===============> "));for (int i = 19; i < 50; i++) {LockA d = list.get(i);System.out.println((i + "\tbefore" + "\t" + JolUtils.toPrintableSimple(d)));synchronized (d) {System.out.println((i + "\tcenter" + "\t" + JolUtils.toPrintableSimple(d)));}System.out.println((i + "\tafter" + "\t" + JolUtils.toPrintableSimple(d)));}}, "t3");t3.start();}
}
结果如下:
0 00000000 00000000 00000000 00000000 00011111 11110010 11000000 00000101
1 00000000 00000000 00000000 00000000 00011111 11110010 11000000 00000101
2 00000000 00000000 00000000 00000000 00011111 11110010 11000000 00000101
3 00000000 00000000 00000000 00000000 00011111 11110010 11000000 00000101
4 00000000 00000000 00000000 00000000 00011111 11110010 11000000 00000101
5 00000000 00000000 00000000 00000000 00011111 11110010 11000000 00000101
6 00000000 00000000 00000000 00000000 00011111 11110010 11000000 00000101
7 00000000 00000000 00000000 00000000 00011111 11110010 11000000 00000101
8 00000000 00000000 00000000 00000000 00011111 11110010 11000000 00000101
9 00000000 00000000 00000000 00000000 00011111 11110010 11000000 00000101
10 00000000 00000000 00000000 00000000 00011111 11110010 11000000 00000101
11 00000000 00000000 00000000 00000000 00011111 11110010 11000000 00000101
12 00000000 00000000 00000000 00000000 00011111 11110010 11000000 00000101
13 00000000 00000000 00000000 00000000 00011111 11110010 11000000 00000101
14 00000000 00000000 00000000 00000000 00011111 11110010 11000000 00000101
15 00000000 00000000 00000000 00000000 00011111 11110010 11000000 00000101
16 00000000 00000000 00000000 00000000 00011111 11110010 11000000 00000101
17 00000000 00000000 00000000 00000000 00011111 11110010 11000000 00000101
18 00000000 00000000 00000000 00000000 00011111 11110010 11000000 00000101
19 00000000 00000000 00000000 00000000 00011111 11110010 11000000 00000101
20 00000000 00000000 00000000 00000000 00011111 11110010 11000000 00000101
21 00000000 00000000 00000000 00000000 00011111 11110010 11000000 00000101
22 00000000 00000000 00000000 00000000 00011111 11110010 11000000 00000101
23 00000000 00000000 00000000 00000000 00011111 11110010 11000000 00000101
24 00000000 00000000 00000000 00000000 00011111 11110010 11000000 00000101
25 00000000 00000000 00000000 00000000 00011111 11110010 11000000 00000101
26 00000000 00000000 00000000 00000000 00011111 11110010 11000000 00000101
27 00000000 00000000 00000000 00000000 00011111 11110010 11000000 00000101
28 00000000 00000000 00000000 00000000 00011111 11110010 11000000 00000101
29 00000000 00000000 00000000 00000000 00011111 11110010 11000000 00000101
30 00000000 00000000 00000000 00000000 00011111 11110010 11000000 00000101
31 00000000 00000000 00000000 00000000 00011111 11110010 11000000 00000101
32 00000000 00000000 00000000 00000000 00011111 11110010 11000000 00000101
33 00000000 00000000 00000000 00000000 00011111 11110010 11000000 00000101
34 00000000 00000000 00000000 00000000 00011111 11110010 11000000 00000101
35 00000000 00000000 00000000 00000000 00011111 11110010 11000000 00000101
36 00000000 00000000 00000000 00000000 00011111 11110010 11000000 00000101
37 00000000 00000000 00000000 00000000 00011111 11110010 11000000 00000101
38 00000000 00000000 00000000 00000000 00011111 11110010 11000000 00000101
39 00000000 00000000 00000000 00000000 00011111 11110010 11000000 00000101
40 00000000 00000000 00000000 00000000 00011111 11110010 11000000 00000101
41 00000000 00000000 00000000 00000000 00011111 11110010 11000000 00000101
42 00000000 00000000 00000000 00000000 00011111 11110010 11000000 00000101
43 00000000 00000000 00000000 00000000 00011111 11110010 11000000 00000101
44 00000000 00000000 00000000 00000000 00011111 11110010 11000000 00000101
45 00000000 00000000 00000000 00000000 00011111 11110010 11000000 00000101
46 00000000 00000000 00000000 00000000 00011111 11110010 11000000 00000101
47 00000000 00000000 00000000 00000000 00011111 11110010 11000000 00000101
48 00000000 00000000 00000000 00000000 00011111 11110010 11000000 00000101
49 00000000 00000000 00000000 00000000 00011111 11110010 11000000 00000101
===============>
0 before 00000000 00000000 00000000 00000000 00011111 11110010 11000000 00000101
0 center 00000000 00000000 00000000 00000000 00100000 01111011 11110001 01110000
0 after 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
1 before 00000000 00000000 00000000 00000000 00011111 11110010 11000000 00000101
1 center 00000000 00000000 00000000 00000000 00100000 01111011 11110001 01110000
1 after 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
2 before 00000000 00000000 00000000 00000000 00011111 11110010 11000000 00000101
2 center 00000000 00000000 00000000 00000000 00100000 01111011 11110001 01110000
2 after 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
3 before 00000000 00000000 00000000 00000000 00011111 11110010 11000000 00000101
3 center 00000000 00000000 00000000 00000000 00100000 01111011 11110001 01110000
3 after 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
4 before 00000000 00000000 00000000 00000000 00011111 11110010 11000000 00000101
4 center 00000000 00000000 00000000 00000000 00100000 01111011 11110001 01110000
4 after 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
5 before 00000000 00000000 00000000 00000000 00011111 11110010 11000000 00000101
5 center 00000000 00000000 00000000 00000000 00100000 01111011 11110001 01110000
5 after 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
6 before 00000000 00000000 00000000 00000000 00011111 11110010 11000000 00000101
6 center 00000000 00000000 00000000 00000000 00100000 01111011 11110001 01110000
6 after 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
7 before 00000000 00000000 00000000 00000000 00011111 11110010 11000000 00000101
7 center 00000000 00000000 00000000 00000000 00100000 01111011 11110001 01110000
7 after 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
8 before 00000000 00000000 00000000 00000000 00011111 11110010 11000000 00000101
8 center 00000000 00000000 00000000 00000000 00100000 01111011 11110001 01110000
8 after 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
9 before 00000000 00000000 00000000 00000000 00011111 11110010 11000000 00000101
9 center 00000000 00000000 00000000 00000000 00100000 01111011 11110001 01110000
9 after 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
10 before 00000000 00000000 00000000 00000000 00011111 11110010 11000000 00000101
10 center 00000000 00000000 00000000 00000000 00100000 01111011 11110001 01110000
10 after 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
11 before 00000000 00000000 00000000 00000000 00011111 11110010 11000000 00000101
11 center 00000000 00000000 00000000 00000000 00100000 01111011 11110001 01110000
11 after 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
12 before 00000000 00000000 00000000 00000000 00011111 11110010 11000000 00000101
12 center 00000000 00000000 00000000 00000000 00100000 01111011 11110001 01110000
12 after 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
13 before 00000000 00000000 00000000 00000000 00011111 11110010 11000000 00000101
13 center 00000000 00000000 00000000 00000000 00100000 01111011 11110001 01110000
13 after 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
14 before 00000000 00000000 00000000 00000000 00011111 11110010 11000000 00000101
14 center 00000000 00000000 00000000 00000000 00100000 01111011 11110001 01110000
14 after 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
15 before 00000000 00000000 00000000 00000000 00011111 11110010 11000000 00000101
15 center 00000000 00000000 00000000 00000000 00100000 01111011 11110001 01110000
15 after 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
16 before 00000000 00000000 00000000 00000000 00011111 11110010 11000000 00000101
16 center 00000000 00000000 00000000 00000000 00100000 01111011 11110001 01110000
16 after 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
17 before 00000000 00000000 00000000 00000000 00011111 11110010 11000000 00000101
17 center 00000000 00000000 00000000 00000000 00100000 01111011 11110001 01110000
17 after 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
18 before 00000000 00000000 00000000 00000000 00011111 11110010 11000000 00000101
18 center 00000000 00000000 00000000 00000000 00100000 01111011 11110001 01110000
18 after 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
19 before 00000000 00000000 00000000 00000000 00011111 11110010 11000000 00000101
19 center 00000000 00000000 00000000 00000000 00011111 11110010 11010001 00000101
19 after 00000000 00000000 00000000 00000000 00011111 11110010 11010001 00000101
20 before 00000000 00000000 00000000 00000000 00011111 11110010 11000000 00000101
20 center 00000000 00000000 00000000 00000000 00011111 11110010 11010001 00000101
20 after 00000000 00000000 00000000 00000000 00011111 11110010 11010001 00000101
21 before 00000000 00000000 00000000 00000000 00011111 11110010 11000000 00000101
21 center 00000000 00000000 00000000 00000000 00011111 11110010 11010001 00000101
21 after 00000000 00000000 00000000 00000000 00011111 11110010 11010001 00000101
22 before 00000000 00000000 00000000 00000000 00011111 11110010 11000000 00000101
22 center 00000000 00000000 00000000 00000000 00011111 11110010 11010001 00000101
22 after 00000000 00000000 00000000 00000000 00011111 11110010 11010001 00000101
23 before 00000000 00000000 00000000 00000000 00011111 11110010 11000000 00000101
23 center 00000000 00000000 00000000 00000000 00011111 11110010 11010001 00000101
23 after 00000000 00000000 00000000 00000000 00011111 11110010 11010001 00000101
24 before 00000000 00000000 00000000 00000000 00011111 11110010 11000000 00000101
24 center 00000000 00000000 00000000 00000000 00011111 11110010 11010001 00000101
24 after 00000000 00000000 00000000 00000000 00011111 11110010 11010001 00000101
25 before 00000000 00000000 00000000 00000000 00011111 11110010 11000000 00000101
25 center 00000000 00000000 00000000 00000000 00011111 11110010 11010001 00000101
25 after 00000000 00000000 00000000 00000000 00011111 11110010 11010001 00000101
26 before 00000000 00000000 00000000 00000000 00011111 11110010 11000000 00000101
26 center 00000000 00000000 00000000 00000000 00011111 11110010 11010001 00000101
26 after 00000000 00000000 00000000 00000000 00011111 11110010 11010001 00000101
27 before 00000000 00000000 00000000 00000000 00011111 11110010 11000000 00000101
27 center 00000000 00000000 00000000 00000000 00011111 11110010 11010001 00000101
27 after 00000000 00000000 00000000 00000000 00011111 11110010 11010001 00000101
28 before 00000000 00000000 00000000 00000000 00011111 11110010 11000000 00000101
28 center 00000000 00000000 00000000 00000000 00011111 11110010 11010001 00000101
28 after 00000000 00000000 00000000 00000000 00011111 11110010 11010001 00000101
29 before 00000000 00000000 00000000 00000000 00011111 11110010 11000000 00000101
29 center 00000000 00000000 00000000 00000000 00011111 11110010 11010001 00000101
29 after 00000000 00000000 00000000 00000000 00011111 11110010 11010001 00000101
30 before 00000000 00000000 00000000 00000000 00011111 11110010 11000000 00000101
30 center 00000000 00000000 00000000 00000000 00011111 11110010 11010001 00000101
30 after 00000000 00000000 00000000 00000000 00011111 11110010 11010001 00000101
31 before 00000000 00000000 00000000 00000000 00011111 11110010 11000000 00000101
31 center 00000000 00000000 00000000 00000000 00011111 11110010 11010001 00000101
31 after 00000000 00000000 00000000 00000000 00011111 11110010 11010001 00000101
32 before 00000000 00000000 00000000 00000000 00011111 11110010 11000000 00000101
32 center 00000000 00000000 00000000 00000000 00011111 11110010 11010001 00000101
32 after 00000000 00000000 00000000 00000000 00011111 11110010 11010001 00000101
33 before 00000000 00000000 00000000 00000000 00011111 11110010 11000000 00000101
33 center 00000000 00000000 00000000 00000000 00011111 11110010 11010001 00000101
33 after 00000000 00000000 00000000 00000000 00011111 11110010 11010001 00000101
34 before 00000000 00000000 00000000 00000000 00011111 11110010 11000000 00000101
34 center 00000000 00000000 00000000 00000000 00011111 11110010 11010001 00000101
34 after 00000000 00000000 00000000 00000000 00011111 11110010 11010001 00000101
35 before 00000000 00000000 00000000 00000000 00011111 11110010 11000000 00000101
35 center 00000000 00000000 00000000 00000000 00011111 11110010 11010001 00000101
35 after 00000000 00000000 00000000 00000000 00011111 11110010 11010001 00000101
36 before 00000000 00000000 00000000 00000000 00011111 11110010 11000000 00000101
36 center 00000000 00000000 00000000 00000000 00011111 11110010 11010001 00000101
36 after 00000000 00000000 00000000 00000000 00011111 11110010 11010001 00000101
37 before 00000000 00000000 00000000 00000000 00011111 11110010 11000000 00000101
37 center 00000000 00000000 00000000 00000000 00011111 11110010 11010001 00000101
37 after 00000000 00000000 00000000 00000000 00011111 11110010 11010001 00000101
38 before 00000000 00000000 00000000 00000000 00011111 11110010 11000000 00000101
38 center 00000000 00000000 00000000 00000000 00011111 11110010 11010001 00000101
38 after 00000000 00000000 00000000 00000000 00011111 11110010 11010001 00000101
===============>
19 before 00000000 00000000 00000000 00000000 00011111 11110010 11010001 00000101
19 center 00000000 00000000 00000000 00000000 00100000 10001011 11110100 10010000
19 after 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
20 before 00000000 00000000 00000000 00000000 00011111 11110010 11010001 00000101
20 center 00000000 00000000 00000000 00000000 00100000 10001011 11110100 10010000
20 after 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
21 before 00000000 00000000 00000000 00000000 00011111 11110010 11010001 00000101
21 center 00000000 00000000 00000000 00000000 00100000 10001011 11110100 10010000
21 after 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
22 before 00000000 00000000 00000000 00000000 00011111 11110010 11010001 00000101
22 center 00000000 00000000 00000000 00000000 00100000 10001011 11110100 10010000
22 after 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
23 before 00000000 00000000 00000000 00000000 00011111 11110010 11010001 00000101
23 center 00000000 00000000 00000000 00000000 00100000 10001011 11110100 10010000
23 after 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
24 before 00000000 00000000 00000000 00000000 00011111 11110010 11010001 00000101
24 center 00000000 00000000 00000000 00000000 00100000 10001011 11110100 10010000
24 after 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
25 before 00000000 00000000 00000000 00000000 00011111 11110010 11010001 00000101
25 center 00000000 00000000 00000000 00000000 00100000 10001011 11110100 10010000
25 after 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
26 before 00000000 00000000 00000000 00000000 00011111 11110010 11010001 00000101
26 center 00000000 00000000 00000000 00000000 00100000 10001011 11110100 10010000
26 after 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
27 before 00000000 00000000 00000000 00000000 00011111 11110010 11010001 00000101
27 center 00000000 00000000 00000000 00000000 00100000 10001011 11110100 10010000
27 after 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
28 before 00000000 00000000 00000000 00000000 00011111 11110010 11010001 00000101
28 center 00000000 00000000 00000000 00000000 00100000 10001011 11110100 10010000
28 after 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
29 before 00000000 00000000 00000000 00000000 00011111 11110010 11010001 00000101
29 center 00000000 00000000 00000000 00000000 00100000 10001011 11110100 10010000
29 after 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
30 before 00000000 00000000 00000000 00000000 00011111 11110010 11010001 00000101
30 center 00000000 00000000 00000000 00000000 00100000 10001011 11110100 10010000
30 after 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
31 before 00000000 00000000 00000000 00000000 00011111 11110010 11010001 00000101
31 center 00000000 00000000 00000000 00000000 00100000 10001011 11110100 10010000
31 after 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
32 before 00000000 00000000 00000000 00000000 00011111 11110010 11010001 00000101
32 center 00000000 00000000 00000000 00000000 00100000 10001011 11110100 10010000
32 after 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
33 before 00000000 00000000 00000000 00000000 00011111 11110010 11010001 00000101
33 center 00000000 00000000 00000000 00000000 00100000 10001011 11110100 10010000
33 after 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
34 before 00000000 00000000 00000000 00000000 00011111 11110010 11010001 00000101
34 center 00000000 00000000 00000000 00000000 00100000 10001011 11110100 10010000
34 after 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
35 before 00000000 00000000 00000000 00000000 00011111 11110010 11010001 00000101
35 center 00000000 00000000 00000000 00000000 00100000 10001011 11110100 10010000
35 after 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
36 before 00000000 00000000 00000000 00000000 00011111 11110010 11010001 00000101
36 center 00000000 00000000 00000000 00000000 00100000 10001011 11110100 10010000
36 after 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
37 before 00000000 00000000 00000000 00000000 00011111 11110010 11010001 00000101
37 center 00000000 00000000 00000000 00000000 00100000 10001011 11110100 10010000
37 after 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
38 before 00000000 00000000 00000000 00000000 00011111 11110010 11010001 00000101
38 center 00000000 00000000 00000000 00000000 00100000 10001011 11110100 10010000
38 after 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
39 before 00000000 00000000 00000000 00000000 00011111 11110010 11000000 00000101
39 center 00000000 00000000 00000000 00000000 00100000 10001011 11110100 10010000
39 after 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
40 before 00000000 00000000 00000000 00000000 00011111 11110010 11000000 00000101
40 center 00000000 00000000 00000000 00000000 00100000 10001011 11110100 10010000
40 after 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
41 before 00000000 00000000 00000000 00000000 00011111 11110010 11000000 00000101
41 center 00000000 00000000 00000000 00000000 00100000 10001011 11110100 10010000
41 after 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
42 before 00000000 00000000 00000000 00000000 00011111 11110010 11000000 00000101
42 center 00000000 00000000 00000000 00000000 00100000 10001011 11110100 10010000
42 after 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
43 before 00000000 00000000 00000000 00000000 00011111 11110010 11000000 00000101
43 center 00000000 00000000 00000000 00000000 00100000 10001011 11110100 10010000
43 after 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
44 before 00000000 00000000 00000000 00000000 00011111 11110010 11000000 00000101
44 center 00000000 00000000 00000000 00000000 00100000 10001011 11110100 10010000
44 after 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
45 before 00000000 00000000 00000000 00000000 00011111 11110010 11000000 00000101
45 center 00000000 00000000 00000000 00000000 00100000 10001011 11110100 10010000
45 after 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
46 before 00000000 00000000 00000000 00000000 00011111 11110010 11000000 00000101
46 center 00000000 00000000 00000000 00000000 00100000 10001011 11110100 10010000
46 after 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
47 before 00000000 00000000 00000000 00000000 00011111 11110010 11000000 00000101
47 center 00000000 00000000 00000000 00000000 00100000 10001011 11110100 10010000
47 after 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
48 before 00000000 00000000 00000000 00000000 00011111 11110010 11000000 00000101
48 center 00000000 00000000 00000000 00000000 00100000 10001011 11110100 10010000
48 after 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
49 before 00000000 00000000 00000000 00000000 00011111 11110010 11000000 00000101
49 center 00000000 00000000 00000000 00000000 00100000 10001011 11110100 10010000
49 after 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
可以看到,此时的t3线程,对于39-50号锁对象并没有执行重偏向,而是直接进行了撤销操作,因此,在t2中执行了19次撤销操作,20次重偏向操作,而在t3中将会至少执行20次撤销操作(重偏向之后不能再次重偏向),此时后续的操作只能进行偏向锁的撤销了。
如果我们将t2线程的i最大值由39改为38,那么此时由于t2+t3线程的总撤销数没有达到39次,因此在执行时,撤销偏向总数没有达到39次,此时对于后续的38-50号锁对象可以执行重偏向:
0 00000000 00000000 00000000 00000000 00100000 00111011 00000000 00000101
1 00000000 00000000 00000000 00000000 00100000 00111011 00000000 00000101
2 00000000 00000000 00000000 00000000 00100000 00111011 00000000 00000101
3 00000000 00000000 00000000 00000000 00100000 00111011 00000000 00000101
4 00000000 00000000 00000000 00000000 00100000 00111011 00000000 00000101
5 00000000 00000000 00000000 00000000 00100000 00111011 00000000 00000101
6 00000000 00000000 00000000 00000000 00100000 00111011 00000000 00000101
7 00000000 00000000 00000000 00000000 00100000 00111011 00000000 00000101
8 00000000 00000000 00000000 00000000 00100000 00111011 00000000 00000101
9 00000000 00000000 00000000 00000000 00100000 00111011 00000000 00000101
10 00000000 00000000 00000000 00000000 00100000 00111011 00000000 00000101
11 00000000 00000000 00000000 00000000 00100000 00111011 00000000 00000101
12 00000000 00000000 00000000 00000000 00100000 00111011 00000000 00000101
13 00000000 00000000 00000000 00000000 00100000 00111011 00000000 00000101
14 00000000 00000000 00000000 00000000 00100000 00111011 00000000 00000101
15 00000000 00000000 00000000 00000000 00100000 00111011 00000000 00000101
16 00000000 00000000 00000000 00000000 00100000 00111011 00000000 00000101
17 00000000 00000000 00000000 00000000 00100000 00111011 00000000 00000101
18 00000000 00000000 00000000 00000000 00100000 00111011 00000000 00000101
19 00000000 00000000 00000000 00000000 00100000 00111011 00000000 00000101
20 00000000 00000000 00000000 00000000 00100000 00111011 00000000 00000101
21 00000000 00000000 00000000 00000000 00100000 00111011 00000000 00000101
22 00000000 00000000 00000000 00000000 00100000 00111011 00000000 00000101
23 00000000 00000000 00000000 00000000 00100000 00111011 00000000 00000101
24 00000000 00000000 00000000 00000000 00100000 00111011 00000000 00000101
25 00000000 00000000 00000000 00000000 00100000 00111011 00000000 00000101
26 00000000 00000000 00000000 00000000 00100000 00111011 00000000 00000101
27 00000000 00000000 00000000 00000000 00100000 00111011 00000000 00000101
28 00000000 00000000 00000000 00000000 00100000 00111011 00000000 00000101
29 00000000 00000000 00000000 00000000 00100000 00111011 00000000 00000101
30 00000000 00000000 00000000 00000000 00100000 00111011 00000000 00000101
31 00000000 00000000 00000000 00000000 00100000 00111011 00000000 00000101
32 00000000 00000000 00000000 00000000 00100000 00111011 00000000 00000101
33 00000000 00000000 00000000 00000000 00100000 00111011 00000000 00000101
34 00000000 00000000 00000000 00000000 00100000 00111011 00000000 00000101
35 00000000 00000000 00000000 00000000 00100000 00111011 00000000 00000101
36 00000000 00000000 00000000 00000000 00100000 00111011 00000000 00000101
37 00000000 00000000 00000000 00000000 00100000 00111011 00000000 00000101
38 00000000 00000000 00000000 00000000 00100000 00111011 00000000 00000101
39 00000000 00000000 00000000 00000000 00100000 00111011 00000000 00000101
40 00000000 00000000 00000000 00000000 00100000 00111011 00000000 00000101
41 00000000 00000000 00000000 00000000 00100000 00111011 00000000 00000101
42 00000000 00000000 00000000 00000000 00100000 00111011 00000000 00000101
43 00000000 00000000 00000000 00000000 00100000 00111011 00000000 00000101
44 00000000 00000000 00000000 00000000 00100000 00111011 00000000 00000101
45 00000000 00000000 00000000 00000000 00100000 00111011 00000000 00000101
46 00000000 00000000 00000000 00000000 00100000 00111011 00000000 00000101
47 00000000 00000000 00000000 00000000 00100000 00111011 00000000 00000101
48 00000000 00000000 00000000 00000000 00100000 00111011 00000000 00000101
49 00000000 00000000 00000000 00000000 00100000 00111011 00000000 00000101
===============>
0 before 00000000 00000000 00000000 00000000 00100000 00111011 00000000 00000101
0 center 00000000 00000000 00000000 00000000 00100000 11000000 11101110 10000000
0 after 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
1 before 00000000 00000000 00000000 00000000 00100000 00111011 00000000 00000101
1 center 00000000 00000000 00000000 00000000 00100000 11000000 11101110 10000000
1 after 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
2 before 00000000 00000000 00000000 00000000 00100000 00111011 00000000 00000101
2 center 00000000 00000000 00000000 00000000 00100000 11000000 11101110 10000000
2 after 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
3 before 00000000 00000000 00000000 00000000 00100000 00111011 00000000 00000101
3 center 00000000 00000000 00000000 00000000 00100000 11000000 11101110 10000000
3 after 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
4 before 00000000 00000000 00000000 00000000 00100000 00111011 00000000 00000101
4 center 00000000 00000000 00000000 00000000 00100000 11000000 11101110 10000000
4 after 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
5 before 00000000 00000000 00000000 00000000 00100000 00111011 00000000 00000101
5 center 00000000 00000000 00000000 00000000 00100000 11000000 11101110 10000000
5 after 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
6 before 00000000 00000000 00000000 00000000 00100000 00111011 00000000 00000101
6 center 00000000 00000000 00000000 00000000 00100000 11000000 11101110 10000000
6 after 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
7 before 00000000 00000000 00000000 00000000 00100000 00111011 00000000 00000101
7 center 00000000 00000000 00000000 00000000 00100000 11000000 11101110 10000000
7 after 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
8 before 00000000 00000000 00000000 00000000 00100000 00111011 00000000 00000101
8 center 00000000 00000000 00000000 00000000 00100000 11000000 11101110 10000000
8 after 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
9 before 00000000 00000000 00000000 00000000 00100000 00111011 00000000 00000101
9 center 00000000 00000000 00000000 00000000 00100000 11000000 11101110 10000000
9 after 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
10 before 00000000 00000000 00000000 00000000 00100000 00111011 00000000 00000101
10 center 00000000 00000000 00000000 00000000 00100000 11000000 11101110 10000000
10 after 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
11 before 00000000 00000000 00000000 00000000 00100000 00111011 00000000 00000101
11 center 00000000 00000000 00000000 00000000 00100000 11000000 11101110 10000000
11 after 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
12 before 00000000 00000000 00000000 00000000 00100000 00111011 00000000 00000101
12 center 00000000 00000000 00000000 00000000 00100000 11000000 11101110 10000000
12 after 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
13 before 00000000 00000000 00000000 00000000 00100000 00111011 00000000 00000101
13 center 00000000 00000000 00000000 00000000 00100000 11000000 11101110 10000000
13 after 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
14 before 00000000 00000000 00000000 00000000 00100000 00111011 00000000 00000101
14 center 00000000 00000000 00000000 00000000 00100000 11000000 11101110 10000000
14 after 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
15 before 00000000 00000000 00000000 00000000 00100000 00111011 00000000 00000101
15 center 00000000 00000000 00000000 00000000 00100000 11000000 11101110 10000000
15 after 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
16 before 00000000 00000000 00000000 00000000 00100000 00111011 00000000 00000101
16 center 00000000 00000000 00000000 00000000 00100000 11000000 11101110 10000000
16 after 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
17 before 00000000 00000000 00000000 00000000 00100000 00111011 00000000 00000101
17 center 00000000 00000000 00000000 00000000 00100000 11000000 11101110 10000000
17 after 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
18 before 00000000 00000000 00000000 00000000 00100000 00111011 00000000 00000101
18 center 00000000 00000000 00000000 00000000 00100000 11000000 11101110 10000000
18 after 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
19 before 00000000 00000000 00000000 00000000 00100000 00111011 00000000 00000101
19 center 00000000 00000000 00000000 00000000 00100000 00111011 00100001 00000101
19 after 00000000 00000000 00000000 00000000 00100000 00111011 00100001 00000101
20 before 00000000 00000000 00000000 00000000 00100000 00111011 00000000 00000101
20 center 00000000 00000000 00000000 00000000 00100000 00111011 00100001 00000101
20 after 00000000 00000000 00000000 00000000 00100000 00111011 00100001 00000101
21 before 00000000 00000000 00000000 00000000 00100000 00111011 00000000 00000101
21 center 00000000 00000000 00000000 00000000 00100000 00111011 00100001 00000101
21 after 00000000 00000000 00000000 00000000 00100000 00111011 00100001 00000101
22 before 00000000 00000000 00000000 00000000 00100000 00111011 00000000 00000101
22 center 00000000 00000000 00000000 00000000 00100000 00111011 00100001 00000101
22 after 00000000 00000000 00000000 00000000 00100000 00111011 00100001 00000101
23 before 00000000 00000000 00000000 00000000 00100000 00111011 00000000 00000101
23 center 00000000 00000000 00000000 00000000 00100000 00111011 00100001 00000101
23 after 00000000 00000000 00000000 00000000 00100000 00111011 00100001 00000101
24 before 00000000 00000000 00000000 00000000 00100000 00111011 00000000 00000101
24 center 00000000 00000000 00000000 00000000 00100000 00111011 00100001 00000101
24 after 00000000 00000000 00000000 00000000 00100000 00111011 00100001 00000101
25 before 00000000 00000000 00000000 00000000 00100000 00111011 00000000 00000101
25 center 00000000 00000000 00000000 00000000 00100000 00111011 00100001 00000101
25 after 00000000 00000000 00000000 00000000 00100000 00111011 00100001 00000101
26 before 00000000 00000000 00000000 00000000 00100000 00111011 00000000 00000101
26 center 00000000 00000000 00000000 00000000 00100000 00111011 00100001 00000101
26 after 00000000 00000000 00000000 00000000 00100000 00111011 00100001 00000101
27 before 00000000 00000000 00000000 00000000 00100000 00111011 00000000 00000101
27 center 00000000 00000000 00000000 00000000 00100000 00111011 00100001 00000101
27 after 00000000 00000000 00000000 00000000 00100000 00111011 00100001 00000101
28 before 00000000 00000000 00000000 00000000 00100000 00111011 00000000 00000101
28 center 00000000 00000000 00000000 00000000 00100000 00111011 00100001 00000101
28 after 00000000 00000000 00000000 00000000 00100000 00111011 00100001 00000101
29 before 00000000 00000000 00000000 00000000 00100000 00111011 00000000 00000101
29 center 00000000 00000000 00000000 00000000 00100000 00111011 00100001 00000101
29 after 00000000 00000000 00000000 00000000 00100000 00111011 00100001 00000101
30 before 00000000 00000000 00000000 00000000 00100000 00111011 00000000 00000101
30 center 00000000 00000000 00000000 00000000 00100000 00111011 00100001 00000101
30 after 00000000 00000000 00000000 00000000 00100000 00111011 00100001 00000101
31 before 00000000 00000000 00000000 00000000 00100000 00111011 00000000 00000101
31 center 00000000 00000000 00000000 00000000 00100000 00111011 00100001 00000101
31 after 00000000 00000000 00000000 00000000 00100000 00111011 00100001 00000101
32 before 00000000 00000000 00000000 00000000 00100000 00111011 00000000 00000101
32 center 00000000 00000000 00000000 00000000 00100000 00111011 00100001 00000101
32 after 00000000 00000000 00000000 00000000 00100000 00111011 00100001 00000101
33 before 00000000 00000000 00000000 00000000 00100000 00111011 00000000 00000101
33 center 00000000 00000000 00000000 00000000 00100000 00111011 00100001 00000101
33 after 00000000 00000000 00000000 00000000 00100000 00111011 00100001 00000101
34 before 00000000 00000000 00000000 00000000 00100000 00111011 00000000 00000101
34 center 00000000 00000000 00000000 00000000 00100000 00111011 00100001 00000101
34 after 00000000 00000000 00000000 00000000 00100000 00111011 00100001 00000101
35 before 00000000 00000000 00000000 00000000 00100000 00111011 00000000 00000101
35 center 00000000 00000000 00000000 00000000 00100000 00111011 00100001 00000101
35 after 00000000 00000000 00000000 00000000 00100000 00111011 00100001 00000101
36 before 00000000 00000000 00000000 00000000 00100000 00111011 00000000 00000101
36 center 00000000 00000000 00000000 00000000 00100000 00111011 00100001 00000101
36 after 00000000 00000000 00000000 00000000 00100000 00111011 00100001 00000101
37 before 00000000 00000000 00000000 00000000 00100000 00111011 00000000 00000101
37 center 00000000 00000000 00000000 00000000 00100000 00111011 00100001 00000101
37 after 00000000 00000000 00000000 00000000 00100000 00111011 00100001 00000101
===============>
19 before 00000000 00000000 00000000 00000000 00100000 00111011 00100001 00000101
19 center 00000000 00000000 00000000 00000000 00100000 11010000 11110001 10010000
19 after 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
20 before 00000000 00000000 00000000 00000000 00100000 00111011 00100001 00000101
20 center 00000000 00000000 00000000 00000000 00100000 11010000 11110001 10010000
20 after 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
21 before 00000000 00000000 00000000 00000000 00100000 00111011 00100001 00000101
21 center 00000000 00000000 00000000 00000000 00100000 11010000 11110001 10010000
21 after 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
22 before 00000000 00000000 00000000 00000000 00100000 00111011 00100001 00000101
22 center 00000000 00000000 00000000 00000000 00100000 11010000 11110001 10010000
22 after 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
23 before 00000000 00000000 00000000 00000000 00100000 00111011 00100001 00000101
23 center 00000000 00000000 00000000 00000000 00100000 11010000 11110001 10010000
23 after 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
24 before 00000000 00000000 00000000 00000000 00100000 00111011 00100001 00000101
24 center 00000000 00000000 00000000 00000000 00100000 11010000 11110001 10010000
24 after 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
25 before 00000000 00000000 00000000 00000000 00100000 00111011 00100001 00000101
25 center 00000000 00000000 00000000 00000000 00100000 11010000 11110001 10010000
25 after 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
26 before 00000000 00000000 00000000 00000000 00100000 00111011 00100001 00000101
26 center 00000000 00000000 00000000 00000000 00100000 11010000 11110001 10010000
26 after 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
27 before 00000000 00000000 00000000 00000000 00100000 00111011 00100001 00000101
27 center 00000000 00000000 00000000 00000000 00100000 11010000 11110001 10010000
27 after 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
28 before 00000000 00000000 00000000 00000000 00100000 00111011 00100001 00000101
28 center 00000000 00000000 00000000 00000000 00100000 11010000 11110001 10010000
28 after 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
29 before 00000000 00000000 00000000 00000000 00100000 00111011 00100001 00000101
29 center 00000000 00000000 00000000 00000000 00100000 11010000 11110001 10010000
29 after 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
30 before 00000000 00000000 00000000 00000000 00100000 00111011 00100001 00000101
30 center 00000000 00000000 00000000 00000000 00100000 11010000 11110001 10010000
30 after 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
31 before 00000000 00000000 00000000 00000000 00100000 00111011 00100001 00000101
31 center 00000000 00000000 00000000 00000000 00100000 11010000 11110001 10010000
31 after 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
32 before 00000000 00000000 00000000 00000000 00100000 00111011 00100001 00000101
32 center 00000000 00000000 00000000 00000000 00100000 11010000 11110001 10010000
32 after 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
33 before 00000000 00000000 00000000 00000000 00100000 00111011 00100001 00000101
33 center 00000000 00000000 00000000 00000000 00100000 11010000 11110001 10010000
33 after 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
34 before 00000000 00000000 00000000 00000000 00100000 00111011 00100001 00000101
34 center 00000000 00000000 00000000 00000000 00100000 11010000 11110001 10010000
34 after 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
35 before 00000000 00000000 00000000 00000000 00100000 00111011 00100001 00000101
35 center 00000000 00000000 00000000 00000000 00100000 11010000 11110001 10010000
35 after 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
36 before 00000000 00000000 00000000 00000000 00100000 00111011 00100001 00000101
36 center 00000000 00000000 00000000 00000000 00100000 11010000 11110001 10010000
36 after 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
37 before 00000000 00000000 00000000 00000000 00100000 00111011 00100001 00000101
37 center 00000000 00000000 00000000 00000000 00100000 11010000 11110001 10010000
37 after 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
38 before 00000000 00000000 00000000 00000000 00100000 00111011 00000000 00000101
38 center 00000000 00000000 00000000 00000000 00100000 00111011 00101001 00000101
38 after 00000000 00000000 00000000 00000000 00100000 00111011 00101001 00000101
39 before 00000000 00000000 00000000 00000000 00100000 00111011 00000000 00000101
39 center 00000000 00000000 00000000 00000000 00100000 00111011 00101001 00000101
39 after 00000000 00000000 00000000 00000000 00100000 00111011 00101001 00000101
40 before 00000000 00000000 00000000 00000000 00100000 00111011 00000000 00000101
40 center 00000000 00000000 00000000 00000000 00100000 00111011 00101001 00000101
40 after 00000000 00000000 00000000 00000000 00100000 00111011 00101001 00000101
41 before 00000000 00000000 00000000 00000000 00100000 00111011 00000000 00000101
41 center 00000000 00000000 00000000 00000000 00100000 00111011 00101001 00000101
41 after 00000000 00000000 00000000 00000000 00100000 00111011 00101001 00000101
42 before 00000000 00000000 00000000 00000000 00100000 00111011 00000000 00000101
42 center 00000000 00000000 00000000 00000000 00100000 00111011 00101001 00000101
42 after 00000000 00000000 00000000 00000000 00100000 00111011 00101001 00000101
43 before 00000000 00000000 00000000 00000000 00100000 00111011 00000000 00000101
43 center 00000000 00000000 00000000 00000000 00100000 00111011 00101001 00000101
43 after 00000000 00000000 00000000 00000000 00100000 00111011 00101001 00000101
44 before 00000000 00000000 00000000 00000000 00100000 00111011 00000000 00000101
44 center 00000000 00000000 00000000 00000000 00100000 00111011 00101001 00000101
44 after 00000000 00000000 00000000 00000000 00100000 00111011 00101001 00000101
45 before 00000000 00000000 00000000 00000000 00100000 00111011 00000000 00000101
45 center 00000000 00000000 00000000 00000000 00100000 00111011 00101001 00000101
45 after 00000000 00000000 00000000 00000000 00100000 00111011 00101001 00000101
46 before 00000000 00000000 00000000 00000000 00100000 00111011 00000000 00000101
46 center 00000000 00000000 00000000 00000000 00100000 00111011 00101001 00000101
46 after 00000000 00000000 00000000 00000000 00100000 00111011 00101001 00000101
47 before 00000000 00000000 00000000 00000000 00100000 00111011 00000000 00000101
47 center 00000000 00000000 00000000 00000000 00100000 00111011 00101001 00000101
47 after 00000000 00000000 00000000 00000000 00100000 00111011 00101001 00000101
48 before 00000000 00000000 00000000 00000000 00100000 00111011 00000000 00000101
48 center 00000000 00000000 00000000 00000000 00100000 00111011 00101001 00000101
48 after 00000000 00000000 00000000 00000000 00100000 00111011 00101001 00000101
49 before 00000000 00000000 00000000 00000000 00100000 00111011 00000000 00000101
49 center 00000000 00000000 00000000 00000000 00100000 00111011 00101001 00000101
49 after 00000000 00000000 00000000 00000000 00100000 00111011 00101001 00000101
4.1.4.3 总结
已经进行了一次重偏向的锁无法再次重偏向,只能进行锁撤销。
批量重偏向和批量撤销都可以看做是轻量级锁的优化操作,并且是针对同一个类的优化,不同的类的使用单独的计数。
当出现多次撤销偏向之后,JVM会认为由另一条线程获取锁的概率更大,此时偏向锁可以进行重偏向到预计的线程Id,这个阈值是20,达到20的时候该类的所有偏向锁将重新偏向当前线程Id,即批量重偏向。
但是,在批量重偏向之后,如果继续出现更多的锁撤销,这个阈值是40,那么JVM认为确实是出现了比较激烈的锁竞争,此时JVM认为偏向锁已没有意义,将会对所有偏向锁进行锁撤销,达到40的时候该类的所有偏向锁将撤销升级为轻量级锁,并且此后该类创建的对象都变成了不可偏向状态。
4.2 轻量级锁
轻量级锁是为了在线程交替执行同步块时提高性能,而偏向锁则是在只有一个线程执行同步块时进一步提高性能。
相比于重量级锁,轻量级锁可以减少传统的重量级锁因为依赖Monitor而导致操作系统产生的性能消耗。因为监视器锁的Monitor是依赖于底层的操作系统的Mutex资源来实现的,因此操作Monitor会导致线程在用户态和核心态(内核态)的转换,这个成本非常高,状态之间的转换需要相对比较长的时间。
当关闭偏向锁功能或者多个线程竞争偏向锁导致偏向锁升级为轻量级锁,则会尝试获取轻量级锁。
4.2.1 轻量级锁加锁
- 在代码进入同步块的时候,首先获取锁对象的Mark Word。判断此锁对象是否是无锁状态(锁标志位为“01”状态,是否为偏向锁为“0”),如果是,则虚拟机首先将在当前线程的栈帧中建立一个名为锁记录(Lock Record)的空间,Lock Record将会存储锁对象无锁状态的Mark Word的拷贝,我们称Lock Record中存储对象mark word的字段叫Displaced Mark Word,然后执行步骤2;如果不是,则说明是加锁状态,则执行步骤3。
- 然后,虚拟机将使用CAS操作尝试将对象头中的Mark Word更新为指向Lock Record即线程栈中锁记录的指针。如果这个更新动作成功了,那么这个线程就拥有了该对象的锁,并且对象Mark Word的锁标志位(Mark Word的最后2bit)将转变为“00”,即表示此对象处于轻量级锁定状态,继续向下执行同步代码;如果CAS失败了则会执行步骤3。
- 继续检查对象的Mark Word的是否指向当前线程栈,如果是说明当前线程已经拥有了这个对象的锁,说明是重入,执行重入逻辑,继续向下执行同步代码;否则说明这个锁对象已经被其他线程抢占了,直接升级至重量级锁。(注意这里,源码中只有一次CAS,失败之后不会自旋重试,所以网上轻量级锁自旋都是讹传)
4.2.2 轻量级锁解锁
执行完同步代码块代码,退出同步代码块,使用CAS开始轻量级锁解锁,线程会使用CAS操作把对象当前的Mark Word和线程中复制的Displaced Mark Word替换回来,如果对象的Mark Word仍然指向着线程的锁记录,就么可能就替换成功,整个同步过程就算完成了,成功释放锁;如果不满足,则释放锁,唤醒被挂起阻塞的线程,开始重量级锁的竞争。
注:当CAS加锁失败时,竞争的线程就会把锁对象Mark Word指向重量级锁,导致Mark Word中的值发生了变化,当原持有轻量级锁的线程执行完毕,尝试通过CAS释放锁时,因为Mark Word已经是指向重量级锁的monitor的指针,不再是指向当前线程Lock Record的指针,于是解锁失败,这时原持有轻量级锁的线程就会知道锁已经升级为重量级锁。
4.2.3 锁重入
synchronized(obj){synchronized(obj){synchronized(obj){}}
}
假设锁的状态是轻量级锁,则线程栈中会包含3个指向当前锁对象的Lock Record。其中栈中最高位的Lock Record为第一次获取锁时分配的,其中Displaced Mark word为锁对象加锁前的Mark Word,而之后的锁重入,则会在线程栈中新分配一个Displaced Mark word为null的Lock Record,用来重入计数。
如下图:
每次重入锁时会将Lock Record放在最后,每次释放锁的时候则会从低到高遍历栈的Lock Record删除对应的Lock Record。 这就是轻量级锁的实现逻辑。
实际上偏向锁的加锁和每次锁重入也会在栈中建立一个Lock Record,解锁时删除Lock Record,因此偏向锁也是基于Lock Record的计数来判断偏向锁的锁重入,以及通过遍历线程栈中的Lock Record来判断是否还在同步块中。只不过偏向锁在释放时仅仅是删除Lock Record,而不会释放对象头中的thread ID,方便下次偏向锁重入。
4.3 重量级锁
在JDK1.6之前,Synchronized是通过对象内部的一个叫做 监视器锁(Monitor)来实现的,synchronized属于重量级锁,效率低下。 因为Monitor是依赖于底层的操作系统的互斥原语mutex来实现,JDK1.6之前实际上加锁时会调用Monitor的enter方法,解锁时会调用Monitor的exit方法,由于java的线程是映射到操作系统的原生线程之上的,如果要操作Monitor对象,都需要操作系统来帮忙完成,这会导致线程在“用户态和内核态”两个态之间来回切换,这个状态之间的转换需要相对比较长的时间,对性能有较大影响。
庆幸的是在JDK1.6之后Java官方对从JVM层面对synchronized较大优化,所以现在的synchronized锁效率也优化得很不错了,JDK1.6之后,为了减少获得锁和释放锁所带来的性能消耗,为了减少这种重量级锁的使用,引入了轻量级锁和偏向锁,这两个锁可以不依赖Monitor的操作。
4.3.1 Monitor详解
当轻量级锁升级为重量级锁之后,它的Markword部分数据中,指针指向的是monitor对象(也称为管程或监视器锁)的起始地址。
每个对象都存在着一个 monitor 与之关联,对象与其 monitor 之间的关系有存在多种实现方式,如monitor可以与对象一起创建销毁或当线程试图获取对象锁时自动生成,但当一个 monitor 被某个线程持有后,它便处于锁定状态。
在Hospot JDK(大部分人使用的JDK)中,monitor对象的具体实现的代码是没有开源的,因为Hospot将底层的调用C++的native方法的具体实现屏蔽了,而monitor对象正是由C++来实现的,但是这部分源码在openjdk上开源了,我们可以在openjdk中查看源码。
在HotSpot虚拟机中,最终采用ObjectMonitor类实现monitor。ObjectMonitor所在目录为:https://hg.openjdk.java.net/jdk8u/jdk8u/hotspot/file/d975dfffada6/src/share/vm/runtime。在下面可以找到如下两个文件:
其中.hpp是c++的头文件,主要定义一些变量,其具体的实现是以cpp中,下面一起来看看objectMonitor.hpp的源码。
首先是ObjectWaiter,ObjectWaiter 顾名思义对象等待者,其实就是对等待锁的线程的封装:
class ObjectWaiter : public StackObj {public:enum TStates { TS_UNDEF, TS_READY, TS_RUN, TS_WAIT, TS_ENTER, TS_CXQ } ;enum Sorted { PREPEND, APPEND, SORTED } ;
// ObjectWaiter 类似一个双向链表ObjectWaiter * volatile _next; // 上一个 ObjectWaiterObjectWaiter * volatile _prev; // 下一个 ObjectWaiterThread* _thread; // 线程jlong _notifier_tid;ParkEvent * _event;volatile int _notified ;volatile TStates TState ;Sorted _Sorted ; // List placement dispositionbool _active ; // Contention monitoring is enabledpublic:ObjectWaiter(Thread* thread);void wait_reenter_begin(ObjectMonitor *mon);void wait_reenter_end(ObjectMonitor *mon);
};
接下来就是ObjectMonitor,来看看初始化的方法的源码:
ObjectMonitor() {//成员变量简单的初始化_header = NULL; //markOop对象头,重量级锁储存锁对象头信息的地方_count = 0;_waiters = 0, //等待线程数_recursions = 0; //锁的重入次数,作用于可重入锁_object = NULL; //监视器锁寄生的对象。锁不是平白出现的,而是寄托存储于对象中。_owner = NULL; //指向持有ObjectMonitor对象的线程地址_WaitSet = NULL; //处于wait状态的线程,会被包装成ObjectWaiter,加入到_WaitSet集合(调用wait方法)_WaitSetLock = 0 ; // 保护等待队列,作用于自旋锁。_Responsible = NULL ;_succ = NULL ;_cxq = NULL ; //阻塞在EntryList上的最近可达的的线程列表FreeNext = NULL ;_EntryList = NULL ; //处于等待锁block阻塞状态的线程,会被包装成ObjectWaiter,加入到该列表_SpinFreq = 0 ;_SpinClock = 0 ;
OwnerIsThread = 0 ;_previous_owner_tid = 0;// 监视器前一个拥有者线程的ID}
ObjectMonitor中有两个队列,_WaitSet 和 _EntryList
,用来保存ObjectWaiter对象列表(每个等待锁的线程都会被封装成ObjectWaiter对象),_owner
则指向持有ObjectMonitor对象的线程。
4.3.2 monitor获取和释放
对于重量级锁,获取锁的过程实际上就是获取monitor的过程,释放锁的过程实际上就是释放monitor的过程。
monitor的竞争获取是在ObjectMonitor的enter方法中,而释放则是在exit方法中。
- 通过
CAS
尝试把monitor的_owner
字段设置为当前线程; - 如果设置之前的
_owner
指向当前线程,说明当前线程再次进入monitor,即重入锁,执行_recursions ++
,记录重入的次数; - 如果之前的
_owner
指向的地址在当前线程中,这种描述有点拗口,换一种说法:之前_owner
指向的BasicLock
在当前线程栈上,说明当前线程是第一次进入该monitor,设置_recursions
为1,_owner
为当前线程,该线程成功获得锁并返回; - 如果获取锁失败,则当前线程包装为ObjectWaiter加入
_EntryList
,等待锁的释放; - 等待时,将会首先通过自旋尝试获取锁, 如果自旋到一定次数还是没有获取到锁,则通过
park
将当前线程挂起,等待被唤醒。这里的park方法是objectMonitor.cpp
中的方法,并不是java中的park方法。 - 当某个持有锁的线程执行完同步代码块时,会进行锁的释放,给其它线程机会执行同步代码,在HotSpot中,通过退出monitor的方式实现锁的释放,并唤醒被阻塞的线程(唤醒操作最终由unpark完成),具体实现入口位于ObjectMonitor的
exit
方法中。 - 被唤醒的线程,继续执行monitor的竞争;
总结:
当多个线程同时访问一段同步代码时,没有获得monitor的对象会进入_EntryList
集合,所谓的获取monitor简单所就是把monitor中的_owner
变量设置为当前线程,同时monitor中的_recursions
加1,若线程调用wait()
方法,将释放当前持有的monitor,_owner
变量恢复为null,_recursions
减一,同时该线程进入 _WaitSet
集合中等待被唤醒。若当前线程执行完毕也将释放monitor并_recursions
减一,以便其他线程进入获取monitor。
如下图所示:
其实Java中的wait、notiy和notifyAll等方法也是依赖于ObjectMonitor对象的内部方法来完成的,这也就是为什么需要在同步方法或者同步代码块中调用的原因(需要先获取对象的锁,才能执行),否则会抛出java.lang.IllegalMonitorStateException的异常。
4.3.3 对象信息存放在哪里
升级重量级锁时,锁对象的markword存储的是对应ObjectMonitor的指针,但是依然持有 原始的对象头分代年龄 hash 是否偏向的信息。它是储存在ObjectMonitor类中有一个markOop类型的_header成员变量中,而这个值,就是在锁膨胀的过程中复制过来的。
4.3.4 自旋锁与自适应自旋
自旋锁是在JDK1.4.2的时候引入的。所谓自旋,就是指当有另外一个线程来竞争锁时,这个线程会在原地循环等待,而不是把该线程给阻塞,直到那个获得锁的线程释放锁之后,这个线程就可以马上获得锁的。在OpenJDK8的synchronized源码中,自旋锁只会在竞争获取重量级锁的时候使用到,并且是自适应自旋,在轻量级锁部分并没有使用到自旋,如果轻量级CAS失败直接升级为重量级锁。
互斥同步对性能最大的影响是阻塞的实现,挂起线程和恢复线程的操作都需要转入内核态中完成,这些操作给系统的并发性能带来了很大的压力。同时,虚拟机的开发团队也注意到在许多应用上,共享数据的锁定状态只会持续很短的一段时间,为了这段时间去挂起和恢复线程并不值得。如果物理机器有一个以上的处理器,能让两个或以上的线程同时并行执行,我们就可以让后面请求锁的那个线程“稍等一下”,但不放弃处理器的执行时间,看看持有锁的线程是否很快就会释放锁。为了让线程等待,我们只需让线程执行一个忙循环(自旋),这项技术就是所谓的自旋锁。
自旋等待不能代替阻塞,且先不说对处理器数量的要求,自旋等待本身虽然避免了线程切换的开销,但它是要占用处理器时间的,因此,如果锁被占用的时间很短,自旋等待的效果就会非常好,反之,如果锁被占用的时间很长,那么自旋的线程只会白白消耗处理器资源,而不会做任何有用的工作,反而会带来性能上的浪费。因此,自旋等待的时间必须要有一定的限度,如果自旋超过了限定的次数仍然没有成功获得锁,就应当使用传统的方式去挂起线程了。
自旋锁在JDK 1.6中默认开启,并且引入了自适应的自旋锁。自适应意味着自旋的时间不再固定了,而是由前一次在同一个锁上的自旋时间及锁的拥有者的状态来决定。如果在同一个锁对象上,自旋等待刚刚成功获得过锁,并且持有锁的线程正在运行中,那么虚拟机就会认为这次自旋也很有可能再次成功,进而它将允许自旋等待持续相对更长的时间,比如100个循环。另外,如果对于某个锁,自旋很少成功获得过,那在以后要获取这个锁时将可能省略掉自旋过程,以避免浪费处理器资源。有了自适应自旋,随着程序运行和性能监控信息的不断完善,虚拟机对程序锁的状况预测就会越来越准确,虚拟机就会变得越来越“聪明”了。
在JDK1.4.2的时候引入了参数-XX:PreBlockSpin来控制自旋次数,默认值是10次。到Sun JDK 1.5.0的最初发布版时,变成只有Win32版的ObjectMonitor::enter()才在用这个参数,其它平台的版本都没有用了。而到Sun JDK 1.6.0的最初发布版时,这个参数已经彻底变成了空壳,只有声明但没有任何地方使用它。也就是说,Sun JDK 1.6.0之后的版本的自旋都是自适应自旋。参见R大的回答:https://www.zhihu.com/question/31187779/answer/51053124
4.4 总体过程和优缺点对比
- 偏向锁:
- 优点:加锁和解锁不需要额外消耗,和执行非同步方法相比,仅存在纳秒级的差距
- 缺点:如果线程间存在竞争,会带来额外开销(偏向锁的撤销)
- 适用场景: 适用于只有一个线程访问同步块的场景
- 轻量锁:
- 优点: 竞争的线程不会造成阻塞,提高了程序的响应速度
- 缺点: 如果始终得不到锁,使用自旋会消耗CPU
- 适用场景: 追求响应时间,同步块执行速度非常快
- 重量锁:
- 优点: 线程竞争不使用自旋,不会消耗CPU
- 缺点: 线程阻塞,响应时间缓慢
- 适用场景: 追求吞吐量,同步块执行速度较慢
总体过程如下:
当关闭了偏向锁的设置,那么就会走右边的流程;反之则走左边的流程:
来自网上大神画的锁升级图:
参考资料:
- 《openJDK8》
- https://tech.youzan.com/javasuo-yu-xian-cheng-de-na-xie-shi/
- 《Java并发编程之美》
- 《Java并发编程的艺术》
- 《深入理解Java虚拟机》
- 《实战高并发编程》
如果有什么不懂或者需要交流,可以留言。另外希望点赞、收藏、关注,我将不间断更新各种Java学习博客!
这篇关于Java synchronized关键字的底层实现以及锁升级优化的原理【一万字】的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!