这是我的Java 1.6类:
public class Foo {
private ArrayList<String> names;
public void scan() {
if (names == null) {
synchronized (this) {
this.names = new ArrayList<String>();
// fill the array with data
}
}
}
}
Findbugs说:
Inconsistent synchronization of com.XXX.Foo.names; locked 40% of time
这是什么意思,我做错了什么?当两个或多个客户同时拨打Foo.scan()
时,我正试图避免出现问题。
答案 0 :(得分:18)
您只是在设置names
变量时才进行同步而不是在阅读时进行同步。因此,在读取和写入之间,另一个线程可以执行,并且您将创建两个ArrayLists并用数据填充它们,第一个创建的将获得GC。
您需要将同步块放在读取和写入周围,或者将synchronized修饰符添加到方法中。
public class Foo {
private ArrayList<String> names;
public void scan() {
synchronized (this)
if (names == null) {
this.names = new ArrayList<String>();
// fill the array with data
}
}
}
}
答案 1 :(得分:7)
第一次在names
内引用scan
超出synchronized
块。
例如,如果从两个不同的线程中调用scan
两次并且names
为空,则可能是这样的
if (names == null)
(到true
)。if (names == null)
被处理(到true
)。synchronized
块,分配names
并离开synchronized
阻止。synchronized
阻止,分配names
并离开synchronized
阻止。现在,names
被初始化两次。这只是一种可能导致意外结果的可能情况。