2:使用同步((>内部的静态最终对象
问题1:为什么在单线图案中,我们需要两个空检查?如果我们仅使用外部检查怎么办?
if (instance == null) {
synchronized (ABC.class) {
// What if we remove this check?
if (instance == null) {
instance = new ABC();
}
}
问题2:以下各项有什么区别:
1:直接使用同步中的类名((
public ABC getInstance() {
if (instance == null) {
// Difference here
synchronized (ABC.class) {
if (instance == null) {
instance = new ABC();
}
}
}
return instance;
}
2:使用同步((>内部的静态最终对象 private static final Object LOCK = new Object();
.
.
public ABC getInstance() {
if (instance == null) {
// Difference here
synchronized (LOCK) {
if (instance == null) {
instance = new ABC();
}
}
}
return instance;
}
3:使用 new Object((内部同步((
if (instance == null) {
// Difference here
synchronized (new Object()) {
if (instance == null) {
instance = new ABC();
}
}
}
private static final Object LOCK = new Object();
.
.
public ABC getInstance() {
if (instance == null) {
// Difference here
synchronized (LOCK) {
if (instance == null) {
instance = new ABC();
}
}
}
return instance;
}
if (instance == null) {
// Difference here
synchronized (new Object()) {
if (instance == null) {
instance = new ABC();
}
}
}
- 删除内部无用检查可能会导致种族条件。想象以下情况:两个线程尝试同时获得对象的实例,因此他们都检查实例是否等于null并获得真实的答案,因此两个线程都会尝试创建对象的实例。由于此代码已同步,因此其中一个线程将输入代码的同步块,而另一个则等待锁定锁定。当第一个线程完成实例化和返回对象实例时,锁将被释放,第二个线程将执行同步块,因此它将创建一个新实例并返回它,因为它不知道它是以前创建的当它在等待它时。
- 使用类作为同步中的参数将生成静态锁。这意味着班级的所有实例都将共享锁。
-
使用对象作为同步的参数,如果您想用特定对象而不是类或此锁定同步块。这使您可以使用同一类中的不同锁具有不同的代码块。例如:
Object o1 = new Object(); Object o2 = new Object(); synchronized(o1) { //your synchronized block } synchronized(o2){ //other synchronized block }
在上一个代码示例中,block1和block2可以同时通过不同的线程执行,因为它们使用了其他锁定对象。如果您在两个代码块(即类(上使用相同的锁,则将块1被阻止,直到块2完成执行,而另一个方面。