我有以下类,它应该是线程安全的:
public class ShouldBeMadeThreadSafe {
private double[] k = {70.0,70.0};
private double[] b = {10.0,10.0};
private double[] m = {5.0,6.0};
public synchronized void setKX(double kx) {k[0]=kx;}
public synchronized void setKY(double ky) {k[1]=ky;}
public synchronized void setBX(double bx) {b[0]=bx;}
public synchronized void setBY(double by) {b[1]=by;}
public synchronized void setMX(double mx) {m[0]=mx;}
public synchronized void setMY(double my) {m[1]=my;}
public double[] getK() {return Arrays.copyOf(k, k.length);}
public double[] getB() {return Arrays.copyOf(b, b.length);}
public double[] getM() {return Arrays.copyOf(m, m.length);}
}
当然,这在 getter 中存在可见性问题,因为只有在监视器的解锁和锁定之间才能保证发生之前的关系。
显而易见的解决方法是将 synchronized 关键字添加到 getter:
public class OkButIDontLikeDeadlocks {
private double[] k = {70.0,70.0};
private double[] b = {10.0,10.0};
private double[] m = {5.0,6.0};
public synchronized void setKX(double kx) {k[0]=kx;}
public synchronized void setKY(double ky) {k[1]=ky;}
public synchronized void setBX(double bx) {b[0]=bx;}
public synchronized void setBY(double by) {b[1]=by;}
public synchronized void setMX(double mx) {m[0]=mx;}
public synchronized void setMY(double my) {m[1]=my;}
public synchronized double[] getK() {return Arrays.copyOf(k, k.length);}
public synchronized double[] getB() {return Arrays.copyOf(b, b.length);}
public synchronized double[] getM() {return Arrays.copyOf(m, m.length);}
}
我不喜欢这个,因为这样我调用了一个持有锁的外星方法,这要求可能的死锁。也许这里不是这种情况,但即便如此我认为它不够优雅(如果我错了,请纠正我)。
现在我想知道以下是否是线程安全的:
public class AmIThreadSafe {
private volatile double[] k = {70.0,70.0};
private volatile double[] b = {10.0,10.0};
private volatile double[] m = {5.0,6.0};
public void setKX(double kx) {k[0]=kx;}
public void setKY(double ky) {k[1]=ky;}
public void setBX(double bx) {b[0]=bx;}
public void setBY(double by) {b[1]=by;}
public void setMX(double mx) {m[0]=mx;}
public void setMY(double my) {m[1]=my;}
public double[] getK() {return Arrays.copyOf(k, k.length);}
public double[] getB() {return Arrays.copyOf(b, b.length);}
public double[] getM() {return Arrays.copyOf(m, m.length);}
}
我不认为这是因为我没有重写 volatile 引用本身。
那么,使 ShouldBeMadeThreadSafe 线程安全的最佳方法是什么?