public static void main(String[] args) {
// 当偏向锁侧撤销操作达到一定的阈值后会批量重偏向
Vector<Object> list = new Vector<>();
Thread t1 = new Thread(() -> {
for (int i = 0; i < 25; i++) {
Object obj = new Object();
list.add(obj);
synchronized (obj){
System.out.println("t1线程的 index = "+ i+" mark word: "+ ClassLayout.parseInstance(obj).toPrintableSimple());
}
}
synchronized (list){
list.notify();
}
}, "t1");
Thread t2 = new Thread(() -> {
synchronized (list){
try {
list.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
for (int i = 0; i < 25; i++) {
Object obj = list.get(i);
// System.out.println("t2线程 第一次 的 index = "+ i+" mark word: "+ ClassLayout.parseInstance(obj).toPrintableSimple());
synchronized (obj){
System.out.println("t2线程第二次 的 index = "+ i+" mark word: "+ ClassLayout.parseInstance(obj).toPrintableSimple());
}
// System.out.println("t2线程第三次 的 index = "+ i+" mark word: "+ ClassLayout.parseInstance(obj).toPrintableSimple());
}
}, "t2");
t1.start();
t2.start();
}
下面是返回的结果,t2在 index =14的时候就已经偏向了而不是在默认的19 ,
我这里面是系统默认值
intx BiasedLockingBulkRebiasThreshold = 20 {product}
intx BiasedLockingBulkRevokeThreshold = 40
下面的结果在 t2线程第二次 的 index = 14 的时候就已经变为偏向锁
t1线程的 index = 0 mark word: 00000000 00000000 00000001 01001000 01001101 11000001 00000000 00000101 (biased: 0x0000000052137040; epoch: 0; age: 0)
.....
t1线程的 index = 24 mark word: 00000000 00000000 00000001 01001000 01001101 11000001 00000000 00000101 (biased: 0x0000000052137040; epoch: 0; age: 0)
t2线程第二次 的 index = 0 mark word: 00000000 00000000 00000000 01000111 00101110 10011111 11110010 10110000 (thin lock: 0x000000472e9ff2b0)
t2线程第二次 的 index = 1 mark word: 00000000 00000000 00000000 01000111 00101110 10011111 11110010 10110000 (thin lock: 0x000000472e9ff2b0)
t2线程第二次 的 index = 2 mark word: 00000000 00000000 00000000 01000111 00101110 10011111 11110010 10110000 (thin lock: 0x000000472e9ff2b0)
t2线程第二次 的 index = 3 mark word: 00000000 00000000 00000000 01000111 00101110 10011111 11110010 10110000 (thin lock: 0x000000472e9ff2b0)
t2线程第二次 的 index = 4 mark word: 00000000 00000000 00000000 01000111 00101110 10011111 11110010 10110000 (thin lock: 0x000000472e9ff2b0)
t2线程第二次 的 index = 5 mark word: 00000000 00000000 00000000 01000111 00101110 10011111 11110010 10110000 (thin lock: 0x000000472e9ff2b0)
t2线程第二次 的 index = 6 mark word: 00000000 00000000 00000000 01000111 00101110 10011111 11110010 10110000 (thin lock: 0x000000472e9ff2b0)
t2线程第二次 的 index = 7 mark word: 00000000 00000000 00000000 01000111 00101110 10011111 11110010 10110000 (thin lock: 0x000000472e9ff2b0)
t2线程第二次 的 index = 8 mark word: 00000000 00000000 00000000 01000111 00101110 10011111 11110010 10110000 (thin lock: 0x000000472e9ff2b0)
t2线程第二次 的 index = 9 mark word: 00000000 00000000 00000000 01000111 00101110 10011111 11110010 10110000 (thin lock: 0x000000472e9ff2b0)
t2线程第二次 的 index = 10 mark word: 00000000 00000000 00000000 01000111 00101110 10011111 11110010 10110000 (thin lock: 0x000000472e9ff2b0)
t2线程第二次 的 index = 11 mark word: 00000000 00000000 00000000 01000111 00101110 10011111 11110010 10110000 (thin lock: 0x000000472e9ff2b0)
t2线程第二次 的 index = 12 mark word: 00000000 00000000 00000000 01000111 00101110 10011111 11110010 10110000 (thin lock: 0x000000472e9ff2b0)
t2线程第二次 的 index = 13 mark word: 00000000 00000000 00000000 01000111 00101110 10011111 11110010 10110000 (thin lock: 0x000000472e9ff2b0)
t2线程第二次 的 index = 14 mark word: 00000000 00000000 00000001 01001000 01001101 11000001 00010001 00000101 (biased: 0x0000000052137044; epoch: 0; age: 0)
t2线程第二次 的 index = 15 mark word: 00000000 00000000 00000001 01001000 01001101 11000001 00010001 00000101 (biased: 0x0000000052137044; epoch: 0; age: 0)
t2线程第二次 的 index = 16 mark word: 00000000 00000000 00000001 01001000 01001101 11000001 00010001 00000101 (biased: 0x0000000052137044; epoch: 0; age: 0)
t2线程第二次 的 index = 17 mark word: 00000000 00000000 00000001 01001000 01001101 11000001 00010001 00000101 (biased: 0x0000000052137044; epoch: 0; age: 0)
t2线程第二次 的 index = 18 mark word: 00000000 00000000 00000001 01001000 01001101 11000001 00010001 00000101 (biased: 0x0000000052137044; epoch: 0; age: 0)
t2线程第二次 的 index = 19 mark word: 00000000 00000000 00000001 01001000 01001101 11000001 00010001 00000101 (biased: 0x0000000052137044; epoch: 0; age: 0)
t2线程第二次 的 index = 20 mark word: 00000000 00000000 00000001 01001000 01001101 11000001 00010001 00000101 (biased: 0x0000000052137044; epoch: 0; age: 0)
t2线程第二次 的 index = 21 mark word: 00000000 00000000 00000001 01001000 01001101 11000001 00010001 00000101 (biased: 0x0000000052137044; epoch: 0; age: 0)
t2线程第二次 的 index = 22 mark word: 00000000 00000000 00000001 01001000 01001101 11000001 00010001 00000101 (biased: 0x0000000052137044; epoch: 0; age: 0)
t2线程第二次 的 index = 23 mark word: 00000000 00000000 00000001 01001000 01001101 11000001 00010001 00000101 (biased: 0x0000000052137044; epoch: 0; age: 0)
t2线程第二次 的 index = 24 mark word: 00000000 00000000 00000001 01001000 01001101 11000001 00010001 00000101 (biased: 0x0000000052137044; epoch: 0; age: 0)
Process finished with exit code 0
在Java 8 中,偏向锁引入了一种新的机制,称为“批量重偏向”(Bulk Rebiasing)。这个机制的主要目的是优化偏向锁的性能,特别是在程序启动时和长时间运行之后的场景。
批量重偏向机制的基本思想是,在一段时间内,如果一个对象被重复访问,那么它会从轻量级锁或无锁状态转换为偏向锁状态。这样,就可以避免频繁地进行偏向锁的撤销和重偏向,从而提高程序的性能。
Java 8 中的批量重偏向机制是通过一个阈值来实现的。当一个线程访问一个偏向锁对象时,它会检查该对象的偏向锁是否已经达到了重偏向的阈值。如果没有达到阈值,那么线程会直接获取该对象的偏向锁。否则,线程会放弃偏向锁,使该对象恢复到无锁状态,并重新进入轻量级锁状态。
那么为什么会出现未到达阈值就已经偏向的情况呢?可能有以下几个原因:
对象被多个线程频繁地访问,导致偏向锁状态无法稳定保持,从而导致偏向锁的撤销和重偏向。
阈值设置得过小,导致对象无法达到重偏向的阈值就被重新偏向。
在某些场景下,可能会出现偏向锁状态的竞争,导致偏向锁的撤销和重偏向。
总之,批量重偏向机制的实现是比较复杂的,它涉及到对象访问的频率、阈值的设置、竞争情况等多个因素。因此,在使用偏向锁时,我们需要根据具体的场景进行合理的设置和调整,以达到最优的性能。