java “不一致的同步”是什么意思?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4187286/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
What "inconsistent synchronization" means?
提问by yegor256
This is my Java 1.6 class:
这是我的 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 says:
Findbugs 说:
Inconsistent synchronization of com.XXX.Foo.names; locked 40% of time
What does it mean and what I'm doing wrong? I'm trying to avoid problems when two or more clients call Foo.scan()
at the same time.
这是什么意思,我做错了什么?当两个或多个客户同时呼叫Foo.scan()
时,我试图避免出现问题。
回答by brain
It's beacuse you are only synchronizing when you set the names
variable and not when you read it. So between the read and the write another thread could execute and you'd create two ArrayLists and fill them with data, the first one created would get GC'ed.
这是因为您只在设置names
变量时同步,而不是在读取时同步。因此,在读取和写入之间,另一个线程可以执行,您将创建两个 ArrayList 并用数据填充它们,创建的第一个将被 GC 处理。
You need to put the synchronized block around the read and the write or add the synchronized modifier to the method.
您需要将同步块放在读取和写入周围,或者向方法添加同步修饰符。
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
}
}
}
}
回答by Nikita Rybak
The first time you reference names
inside scan
is outside of synchronized
block.
E.g., if scan
is called twice from two different threads and names
is null, it may go like this
第一次引用names
insidescan
是在synchronized
块外。
例如,如果scan
从两个不同的线程调用两次并且names
为空,它可能会像这样
if (names == null)
from the first thread is processed (totrue
).if (names == null)
from the second thread is processed (totrue
).- First thread enters
synchronized
block, assignesnames
and leavessynchronized
block. - Second thread enters
synchronized
block, assignesnames
and leavessynchronized
block.
if (names == null)
从第一个线程被处理(到true
)。if (names == null)
从第二个线程被处理(到true
)。- 第一个线程进入
synchronized
块,分配names
并离开synchronized
块。 - 第二个线程进入
synchronized
块,分配names
和离开synchronized
块。
Now, names
is initialized twice. And this is only one possible scenario where you get unexpected results.
现在,names
初始化了两次。这只是您获得意外结果的一种可能情况。