Java 并发访问:波动性和同步

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

我已经阅读了很多关于同步和易失性关键字/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() {
    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(),我相信它会以正确的方式更改其状态,甚至在计算前提条件之前,不是吗?