java - 并发访问 : volatility and synchronization

标签 java

我已经阅读了很多关于 synchronized 和 volatile 关键字/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在调用 X 的 setter 时,对一组(在本例中只有一个)引用值进行分类目的。问题是:

  1. 可以x仍被声明为 volatile并确保所有线程的共同可见性或需要进一步同步?
  2. 想法是让类的所有对象Y不可变的。所以,我假设它的所有字段也必须是不可变的。制作 Y 的最佳方法是什么?用户可实现但同时又是线程安全的?一个实现线程安全机制的抽象类,然后它可以扩展?目前,Y是一个带有getter方法的接口(interface),可以实现,当然不是线程安全的。
  3. 是否从并发访问的角度正确实现了启动/停止机制?

最佳答案

问题的症结在于 private volatile Y yObj; 只会使 yObj 引用 volatile,而不是其内容。

当您稍后执行 x = yObj.getY(); 时,您可能会请求访问非 volatile 变量,这在理论上可能是线程不安全的。

使 yObj 不可变可能会有所帮助,但执行起来会很困难。

您的启动/停止机制看起来不错,但我会使用 AtomicBoolean,放弃同步并使用 if(active.compareAndSet(false, true) { ...或类似的。

关于java - 并发访问 : volatility and synchronization,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17901593/

相关文章:

java - 对于 Junit 问题 : when test multiple thread

java - 从 HDFS 读取数据 - 我的程序找不到路径

java - 如何解决java中的启动类型错误?

java - InputStream.read(byte[], 0 length) 提前停止?

java - 使 JFrame 不重绘

java - 如何在 netbeans 中的 java fxml 应用程序中编译时删除警告

java - 如何在JSP的按钮单击事件上调用Java方法

java - 如果选择"is",则用户返回主菜单

java - gradle with openjdk 14 不支持的类文件主要版本 58

Java:在不使用 QName 的情况下读取具有动态添加元素的 xml 文件