Java 并发访问:波动性和同步
我已经阅读了很多关于同步和易失性关键字/IDOM的帖子,我认为我正确理解了它们的工作原理以及应该在何时使用它们。然而,我仍然对我正在尝试做的事情有些怀疑。考虑以下事项:Java 并发访问:波动性和同步,java,Java,我已经阅读了很多关于同步和易失性关键字/IDOM的帖子,我认为我正确理解了它们的工作原理以及应该在何时使用它们。然而,我仍然对我正在尝试做的事情有些怀疑。考虑以下事项: public class X { private volatile int x; public X(int x) { this.x = x; } public void setX(int x) { this.x = x; } public int getX() { ret
public class X {
private volatile int x;
public X(int x) {
this.x = x;
}
public void setX(int x) {
this.x = x;
}
public int getX() {
return x;
}
}
上面的一个是非常直接和线程安全的。现在考虑同一类X的变化:
public class X {
private volatile int x;
private volatile Y yObj;
private volatile boolean active;
public X(Y yObj) {
this.yObj = yObj;
active = false;
x = yObj.getY();
}
public void setX(int x) {
if (active) throw new IllegalStateException()
if (!yObj.isValid(x)) throw new IllegalArgumentException();
this.x = x;
}
public void setY(Y yObj) {
if (active) throw new IllegalStateException();
this.yObj = yObj;
x = yObj.getY();
}
public int getX() {
return x;
}
public Y getY() {
return yObj;
}
public synchronized void start() {
if (active) throw new IllegalStateException();
/*
* code that performs some initializations and condition checking runs here
* does not depend on x and yObj
* might throw an exception
*/
active = true;
}
public synchronized void stop() {
if (!active) throw new IllegalStateException();
/* some code in the same conditions of the comments in the start()
* method runs here
*/
active = false;
}
public boolean isActive() {
return active;
}
}
现在,我将yObj
声明为volatile
,以确保通过调用setY(Y)
方法更改时,每个线程都能看到相同的对象引用。Y
类的思想是在调用X
对象的setter时提供X
类a集合(在本例中仅一个)的参考值。问题是:
x
是否仍然可以声明为volatile
,并确保所有线程的通用可见性或需要进一步同步Y
的所有对象都不可变。所以,我假设它的所有字段也必须是不可变的。使Y
用户可实现但同时又是线程安全的最佳方法是什么?一个实现线程安全机制的抽象类,然后它可以扩展?目前,Y
是一个带有getter方法的接口,可以实现,当然不是线程安全的你问题的症结在于
private volatile Y yObj
仅使yObj
引用易失性
,而不是其内容
当您稍后执行x=yObj.getY()时代码>您可能请求访问一个非易失性变量,从理论上讲,这可能导致线程不安全
使yObj
不可变可能会有所帮助,但实施起来会很困难
您的启动/停止机制看起来很好,但我会使用一个原子布尔值,放弃同步并使用if(active.compareAndSet(false,true){…
或类似值。setY
例如使用两个非同步操作。getX()
可能看不到新的x
,但是新的yObj
。这可能不是线程安全的。另外setX
和setY
也不安全,您可以从setX得到x,但从setX得到ysetY@zapl你说得对,错过了。谢谢你指出这一点!是的,我知道宣布yObj为易失性只会让裁判erence volatile,而不是它的内容。关于问题#2.执行它有那么困难吗?如果Y只提供简单的getter和setter,那么仅仅声明其成员volatile不是很简单吗?启动/停止机制可能抛出和异常,因此,在这种情况下,标志不能更改其sta调用compareAndSet(),我相信它会以正确的方式更改其状态,甚至在计算前提条件之前,不是吗?