在Brian Goetz等人的Java Concurrency in Practice中,有以下示例(列出4.11缩短版)。
public class SafePoint {
private int x, y;
public SafePoint(int x, int y) {
this.x = x;
this.y = y;
}
public synchronized int[] get() {
return new int[] { x, y };
}
public synchronized void set(int x, int y) {
this.x = x;
this.y = y;
}
}
它真的是线程安全的吗? x和y既不是volatile也不是final,并且它们设置时没有锁定,这意味着调用get()的另一个线程可能会看到过时的值(零)。我在这里想念一下吗?
答案 0 :(得分:3)
它真的是线程安全的吗?
是
x和y既不是易变的也不是最终的,
正确,但......
并且在没有锁定的情况下设置它们
不正确的。 get和set方法是synchronized
方法,这意味着它们隐式锁定并在this
上同步。
实际上......有一点需要注意。在创建SafePoint
实例和某个其他线程上的(第一个)get
或set
调用之间,之前也必须发生。如果没有,那么get
或set
可能会看到x
和y
的默认值,而不是传递给构造函数的值。
Goetz等人在Java Concurrency in Practice的下一页中介绍了这一点......尽管他们使用比 hb 关系更高级别的推理。在清单4.12中,他们使用ConcurrentHashMap
来确保SafePoint
安全发布。