在 Java 中读取双精度可以线程安全吗?



假设我有一个类,如下所示:

public class vector{
public vector(double x, double y){
this.x = x;
this.y = y;
}
public double getDist() {
return Math.sqrt(x*x + y*y);
}
}

此代码是否与线程一起安全运行? 我有点困惑,因为我知道双打的阅读 不是原子的,但是因为这个类没有 setter 或 getter,所以需要做任何事情来确保它是线程安全的?

谢谢

我有点困惑,因为我知道双打的读取不是原子的,但是因为这个类没有二传手或getters,所以需要做些什么来确保这是线程安全的?

是的,您需要确保xy标记为final. 然而,这与它double无关。final字段保证在构造vector(应该Vector顺便说一句)时完全初始化。 如果没有final,如果您共享了未同步的vector实例,编译器可以在构造函数完成时对字段初始化重新排序,并且xy字段可能未初始化或部分初始化。 因此,另一个线程可能会看到xy为 0 或仅更新其中一个单词。 有关更多信息,请参阅 Java 中的构造函数同步

如果您正在处理可变字段(无法final),那么double是否会完全更新取决于您正在运行的体系结构。 为了安全起见,您必须将它们volatile,以确保它们在更改时已完全更新和发布。

正如@Voo指出的那样,如果您正在更新x然后y那么这是 2 个单独的操作,您的距离计算可能只看到两个字段中的一个更新 - 即使它们都是volatile。 如果你需要它是原子的,那么你应该使用一个AtomicReference,并有一个保存xy的小容器类。AtomicReference包裹着volatile Object.

像这样:

private final AtomicReference<XAndY> xyRef = new AtomicReference<XAndY>();
...
public void setXAndY(double x, double y) {
xyRef.set(new XAndY(x, y));
}
...
public double getDist() {
// get a local instance of our object which is atomic
XAndY xAndY = xyRef.get();
return Math.sqrt(xAndY.x * xAndY.x + xAndY.y * xAndY.y);
}
...
private static class XAndY {
double x;
double y;
}

最新更新