一、原理
synchronized关键字是Java中用于实现线程同步
的重要机制,它可以确保多个线程对共享资源的安全访问。在JVM底层,synchronized的实现涉及到对象头(Object Header)
、monitor对象监视器
等概念。
当一个线程进入synchronized代码块时,会尝试获取对象的monitor对象监视器
,如果对象的monitor对象尚未被锁定,线程会成功获取锁并继续执行;如果对象的monitor对象已经被其他线程锁定,当前线程会进入阻塞状态
等待锁释放。
在JVM底层,每个Java对象都会有一个与之关联的monitor对象
,monitor对象包含了锁的信息、持有锁的线程、等待队列
等。当一个线程获取了对象的monitor对象锁时,会在monitor对象上记录持有锁的线程,并将锁计数器加一
;其他线程尝试获取锁时,会进入等待队列
等待锁释放。
在JVM中,synchronized关键字的底层实现是通过monitorenter
和monitorexit
两条指令来实现的。当进入synchronized代码块时,会执行monitorenter指令来尝试获取对象的monitor对象锁;当退出synchronized代码块时,会执行monitorexit指令来释放对象的monitor对象锁。
二、synchronized代码如下
public class SynchronizedExample extends Thread{
public static void main(String[] args) {
new SynchronizedExample().start();
}
public void run() {
test();
}
public void test() {
synchronized (this) {
System.out.println("Thread 1 acquired the lock");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
System.out.println("Thread 1 released the lock");
}
}
}
上面代码中创建了两个线程 thread1 和 thread2 ,它们都尝试使用相同的 lock 对象进行同步。当 thread1 获取了 lock 对象的monitor对象锁时, thread2 尝试获取锁时会被阻塞,直到 thread1 释放锁后才能获取锁。
三、使用javap反编译查看原理
javap -c SynchronizedExample
使用javap可以的到类对应的字节码指令
Compiled from "SynchronizedExample.java"
public class SynchronizedExample extends java.lang.Thread {
public SynchronizedExample();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Thread."<init>":()V
4: return
public static void main(java.lang.String[]);
Code:
0: new #2 // class SynchronizedExample
3: dup
4: invokespecial #3 // Method "<init>":()V
7: invokevirtual #4 // Method start:()V
10: return
public void run();
Code:
0: aload_0
1: invokevirtual #5 // Method test:()V
4: return
public void test();
Code:
0: aload_0
1: dup
2: astore_1
3: monitorenter
4: getstatic #6 // Field java/lang/System.out:Ljava/io/PrintStream;
7: ldc #7 // String Thread 1 acquired the lock
9: invokevirtual #8 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
12: ldc2_w #9 // long 2000l
15: invokestatic #11 // Method java/lang/Thread.sleep:(J)V
18: goto 28
21: astore_2
22: invokestatic #13 // Method java/lang/Thread.currentThread:()Ljava/lang/Thread;
25: invokevirtual #14 // Method java/lang/Thread.interrupt:()V
28: getstatic #6 // Field java/lang/System.out:Ljava/io/PrintStream;
31: ldc #15 // String Thread 1 released the lock
33: invokevirtual #8 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
36: aload_1
37: monitorexit
38: goto 46
41: astore_3
42: aload_1
43: monitorexit
44: aload_3
45: athrow
46: return
Exception table:
from to target type
12 18 21 Class java/lang/InterruptedException
4 38 41 any
41 44 41 any
}