当前位置 博文首页 > 庆述倾述:synchronized 关键字的同步语句块
比如单例模式:
public class Singleton {
private Singleton(){}
private volatile static Singleton uniqueSingleton;
public static Singleton getUniqueSingleton(){
if(uniqueSingleton == null){
synchronized(Singleton.class){
if(uniqueSingleton == null){
uniqueSingleton = new Singleton();
}
}
}
return uniqueSingleton;
}
}
使用volatile
来保证可见性以及禁止指令重排,保证有序性,但不保证原子性。
使用javap -c Singleton.class
查看相关字节码信息:
Compiled from "Singleton.java"
public class com.weizu.code.Singleton {
public static com.weizu.code.Singleton getUniqueSingleton();
Code:
0: getstatic #2 // Field uniqueSingleton:Lcom/weizu/code/Singleton;
3: ifnonnull 37
6: ldc #3 // class com/weizu/code/Singleton
8: dup
9: astore_0
10: monitorenter
11: getstatic #2 // Field uniqueSingleton:Lcom/weizu/code/Singleton;
14: ifnonnull 27
17: new #3 // class com/weizu/code/Singleton
20: dup
21: invokespecial #4 // Method "<init>":()V
24: putstatic #2 // Field uniqueSingleton:Lcom/weizu/code/Singleton;
27: aload_0
28: monitorexit
29: goto 37
32: astore_1
33: aload_0
34: monitorexit
35: aload_1
36: athrow
37: getstatic #2 // Field uniqueSingleton:Lcom/weizu/code/Singleton;
40: areturn
Exception table:
from to target type
11 29 32 any
32 35 32 any
}
synchronized
同步语句块的实现使?的是 monitorenter
和 monitorexit
指令,其中 monitorenter
指令指向同步代码块的开始位置,monitorexit
指令则指明同步代码块的结束位置。
当执行 monitorenter
指令时,线程试图获取锁也就是获取 monitor
(monitor
对象存在于每个Java
对象的对象头中,synchronized
锁便是通过这种方式获取锁的,也是为什么Java
中任意对象可以作为锁的原因) 的持有权.当计数器为0
则可以成功获取,获取后将锁计数器设为1
也就是加1
。相应的在执行 monitorexit
指令后,将锁计数器设为0
,表明锁被释放。如果获取对象锁失败,那当前线程就要阻塞等待,直到锁被另外一个线程释放为止。