此代码用于演示双重检查锁定反模式:
@NotThreadSafe
public class DoubleCheckedLocking {
private static Resource resource;
public static Resource getInstance() {
if (resource == null) {
synchronized (DoubleCheckedLocking.class) {
if (resource == null)
resource = new Resource();
}
}
return resource;
}
}
我可以通过将其修改为:
来避免此问题@NotThreadSafe
public class DoubleCheckedLocking {
private static Resource resource;
public static Resource getInstance() {
if (resource == null) {
synchronized (DoubleCheckedLocking.class) {
if (resource == null){
Resource r=new Resource();
resource = r;
}
}
}
return resource;
}
}
据我所知,
Resource r=new Resource();
resource = r;
该编译器应为此提供事先发生的关系。
答案 0 :(得分:4)
据我所知,双重检查锁定模式的唯一已知实现(对于JDK5及更高版本)使用'volatile'关键字。 See Fixing Double-Checked Locking using Volatile
答案 1 :(得分:2)
public static Resource getInstance() {
if (resource == null) {
synchronized (DoubleCheckedLocking.class) {
if (resource == null){
Resource r=new Resource();
resource = r;
}
}
}
return resource;
}
保证线程之间正确可见性的唯一方法是通过同步(通过synchronized
,volatile
,...)创建同步与关系。
如果您没有 synchronize-with 关系,则不需要线程来查看其他线程的修改。
在这种情况下,线程可以创建Resource
并在resource
中存储对它的引用。然后第二个帖子可能会输入getInstance()
,并看resource != null
。第二个线程不能保证看到resource
构造的所有效果,因为它不是与第一个线程同步。
答案 2 :(得分:2)
允许编译器进行优化:
Resource r=new Resource();
resource = r;
到
resource=new Resource();
所以你的调整无效。