假设我有一个实例变量,我有setter和getters。
代码1:
Class<T> {
volatile T value;
public synchronized void set(T v) {
if(value==null) {
value=v;
}
}
public T get() {
return value;
}
}
代码2:
Class<T> {
static volatile T value;
public synchronized void set(T v) {
if(value==null) {
value=v;
}
}
public T get() {
return value;
}
}
我有两个问题
1)静态易失性状态字段和仅易失性状态字段有什么区别?
2)我刚刚了解了易失性读/写的发布/获取概念,并了解到没有必要同步getter(因为缓存刷新)。但是有没有需要同步setter?
答案 0 :(得分:0)
让我们从你的第二个问题开始:
我认为您在设置器中使用同步块的原因是您在value
上执行两个不同的操作。您检查value==null
,然后设置value=v
。虽然您在每个步骤中都有锁定,但它们之间没有锁定。所以这是可能的:
Thread1: lock value -> value==null (true) -> release value
Thread2: lock value -> value==null (true) -> release value
Thread1: lock value -> value=v -> release value;
Thread2: lock value -> value=v -> release value;
所以你仍然有竞争条件。
现在回到你的第一个问题:你应该使用static来让你的类的任何实例使用相同的变量T而不是拥有自己的变量。
答案 1 :(得分:-2)
在代码2中,可能存在以下情况:
Thread1: calls set(X) on instance1
Thread1: value is null, entering inside if
Thread2: calls set(Y) on onstance2
Thread2: value is null, entering inside if
Thread2: setting value = Y
Thread1: setting value = X
问题是在类的实例上获取了锁,而不是类本身。如果您要将set
和get
方法更改为static
,那么它会再次正常工作。