在并发编程中,Java提供了关键字Synchronized作为一种内置锁机制来支持原子性,使用Synchronize语义的同步代码块包括两个部分组成:一个作为锁的对象引用,一个作为由这个锁保护的代码块。
synchronized (lock){
//...
}
编写一个简单的Synchronized测试代码
public class SyncPrintTest {
private static final Object lock = new Object();
public void print() {
synchronized (lock){
System.out.println("Hello Synchronize!");
}
}
}
class文件编译后,使用javap -c SyncPrintTest查看字节码 可以看到由synchronized修饰的代码块,在代码块前后分别插入monitorenter和monitorexit指令。
public com.yupaopao.test.SyncPrintTest();
Code:
0: aload_0
1: invokespecial #1
4: return
public void print();
Code:
0: getstatic #2
3: dup
4: astore_1
5: monitorenter //这里是synchronized获取锁的字节码
6: getstatic #3
9: ldc #4
11: invokevirtual #5
14: aload_1
15: monitorexit
16: goto 24
19: astore_2
20: aload_1
21: monitorexit //这里是synchronized释放锁的字节码
22: aload_2
23: athrow
24: return
Exception table:
from to target type
6 16 19 any
19 22 19 any
static {};
Code:
0: new #6
3: dup
4: invokespecial #1
7: putstatic #2
10: return
}
MarkWord
Synchronized是基于对象的锁,每个对象的脑袋上都顶着一个叫MarWord的东东,看看这个MarWord长啥样
通过一段测试代码来看一下对象头信息
public class SynchronizedTest {
private static Object lock = new Object();
public static void main(String[] args) {
System.out.println(ClassLayout.parseInstance(lock).toPrintable());
synchronized (lock){
System.out.println(ClassLayout.parseInstance(lock).toPrintable());
}
}
}
使用OpenJdk的工具类,输出对象头信息,在工程中的pom文件中增加maven坐标
<dependency>
<groupId>org.openjdk.jol</groupId>
<artifactId>jol-core</artifactId>
<version>0.8</version>
</dependency>
对象头输出结果
JVM默认4秒后开启偏向锁,可以在启动参数里设置-XX:BiasedLockingStartupDelay=0,重新执行后可以看到偏向锁
Synchronized在字节码中的体现
被Synchronized修饰的方法或代码块在JVM中到底是如何执行的?本文从JVM和操作系统来分析Synchronized底层原理。
既然Synchronized是Java的关键字,那么在编译后的字节码中可以看到Synchronized生成的字节码指令。 可以看到synchronized实现同步锁的机制是依靠插入的monitorenter和monitorexit指令,即锁监视器,那么这两个指令在JVM中又是如何执行的? 在HotSpot虚拟机中,monitorenter和monitorexit指令执行的的源码在InterpreterRuntime.cpp文件中
JVM执行monitorenter方法
Monitor介绍
未完待续...