这是我面临的问题。在运行下面的代码时,有时在打印B的内容时会得到陈旧的数据。我真不明白为什么会这样,因为更新和接收B的内容受B的锁保护。
请注意,在更新到B的过程中,A和B的锁均被保持。
访问B的内容时,仅持有一个锁。
还要注意,B.updated()没有同步,但是我不认为这是问题所在,因为在我访问B的内容之前,请确保已将更新的计数器设置为2。
class B {
Object data
int updated = 0
// get and set protected by B's monitor
synchronized Object getData() {
return data;
}
synchronized setData(Object d) {
data = d;
updated += 1;
}
// deliberately not synchronized
int updated() { return updated; }
}
class A {
B b
A() {
new Thread t = new Thread(new UpdaterThread());
t.start();
}
// when B is updated both A and B monitors are held
synchronized String setB(Object data) {
b.setData(data);
}
class UpdateThread implements Runnable {
public void run() {
// updating B to new Value
setB("B2");
}
}
}
public static void main(String[] _) {
B b = new B();
b.setData("B1");
A a = new A();
while (b.updated() == 1) {
// wait for updated to reach 2
}
println(b.getData()); // prints "B1" sometimes, but very rarely.
}
最佳答案
您期望代码为sequentially consistent。但是,如果代码中没有数据争用,则Java仅保证顺序一致性。
那就是问题所在。您对已更新的变量进行了数据竞争,因为一个线程向其写入数据,而另一个线程在不进行任何同步的情况下从该线程读取数据。
如果您将变量volatile
设置为,则该代码将起作用,因为volatile
变量上没有数据争用。