我有以下类,它应该是线程安全的:
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);}
}
Run Code Online (Sandbox Code Playgroud)
当然,这在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);}
}
Run Code Online (Sandbox Code Playgroud)
我不是这个人的粉丝,因为这种方式我正在调用一个持有锁的外来方法,这就是要求可能的死锁.也许情况并非如此,但即便如此,我也不认为它足够优雅(如果我错了,请纠正我).
现在我想知道以下是否是线程安全的:
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);}
}
Run Code Online (Sandbox Code Playgroud)
我不认为这是因为我没有重写易失性参考本身.
那么,什么是使ShouldBeMadeThreadSafe线程安全的最佳方法?
您误解了不要将外国代码称为持锁的建议.Arrays.copyOf 不是外来代码:它是JDK精确识别,精确指定的方法.外来代码的情况将是这样的:
public synchronized double[] getK(Runnable r) { r.run(); return k; };
Run Code Online (Sandbox Code Playgroud)
在这里,您正在执行run一个完全未知的类的方法,它可能会调用您的其他方法之一,从而破坏不变量.
synchronized在所有方法上使用都非常好; 是的,volatile不会帮助你.
| 归档时间: |
|
| 查看次数: |
73 次 |
| 最近记录: |