一、在方法上通过synchronized加锁
[Java]
纯文本查看
复制代码
1
2
3
4
5
6
7
8
9
|
public
class
SingleteExample {
private
static
SingleteExample singleteExample;
[p=
30
,
2
, left]
private
SingleteExample() {
}[/p][p=
30
,
2
, left]
public
synchronized
static
SingleteExample getInstance() {[/p][/size][/font][p=
30
,
2
, left][font=微软雅黑][size=
3
]
if
(singleteExample ==
null
) {
singleteExample =
new
SingleteExample();
}
return
singleteExample;
}
}
|
这种方法可以保证线程安全,但性能会非常差,特别是在并发情况下,当一个线程执行这个方法的时候,其他线程都会被阻塞。
二 在代码块上通过synchronized加锁
[Java]
纯文本查看
复制代码
01
02
03
04
05
06
07
08
09
10
11
12
|
public
class
SingleteExample2 {
private
static
SingleteExample2 singleteExample;
[p=
30
,
2
, left]
private
SingleteExample2() {
}[/p][/size][/font][p=
30
,
2
, left][font=微软雅黑][size=
3
]
public
static
SingleteExample2 getInstance() {
if
(singleteExample ==
null
) {
synchronized
(SingleteExample2.
class
) {
singleteExample =
new
SingleteExample2();
}
}
return
singleteExample;
}
}
|
这种方法只有在SingleteExample2对象为空时才会创建对象,细化了锁的力度,但在并发情况下,线程A,B同时执行这个方法,同时进行判断,都为空,A线程得到锁,初始化,
B线程等A线程释放锁后,B线程接着进行初始化,A B两个线程得到的不是同一个对象。
三 双重检查
[Java] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
|
public class SingleteExample3 {
private static SingleteExample3 singleteExample;
private SingleteExample3() {
}
public static SingleteExample3 getInstance() {
if (singleteExample == null ) {
synchronized (SingleteExample3. class ) {
if (singleteExample == null ) {
singleteExample = new SingleteExample3();
}
}
}
return singleteExample;
}
}
|
B线程得到锁后初始化前仍会判断SingleteExample3对象是否为空,这时SingleteExample3对象已经初始化了,判断结果为false,B不会再次创建对象。
四 指令重排序
创建一个对象分为三步 1.分配内存空间 2.初始化对象 3.将内存空间的地址赋值给对象的引用。
其中2、3步执行时虚拟机是会重排序的。若A线程执行时JVM将2 3步重排序,那么此时对象的引用指向的内存空间仅仅只是一个地址,
这时候B线程进行第一次为空判断时,发现不为空,会将对象的引用返回。使用volatile关键字禁止JVM重排序。
[Java]
纯文本查看
复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
|
public
class
SingleteExample4 {
private
static
volatile
SingleteExample4 singleteExample;[/size]
[p=
30
,
2
, left][size=
3
]
private
SingleteExample4() {
}[/size][/p][p=
30
,
2
, left][size=
3
]
public
static
SingleteExample4 getInstance() {
if
(singleteExample ==
null
) {
synchronized
(SingleteExample4.
class
) {
if
(singleteExample ==
null
) {
singleteExample =
new
SingleteExample4();
}
}
}
return
singleteExample;
}
}
|