3

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;
  }
} 

ここで、メソッドの呼び出しによって変更されたときに、すべてのスレッドが同じオブジェクト参照を参照するようにyObjasを宣言しました。クラスの考え方は、オブジェクトのセッターを呼び出すときに参照値のセット (この例では 1 つだけ) をクラスに提供することです。質問は次のとおりです。volatilesetY(Y)YXX

  1. xとして宣言しvolatile、すべてのスレッドの共通の可視性を確保するか、さらに同期する必要がありますか?
  2. アイデアは、クラスのすべてのオブジェクトをY不変にすることです。したがって、そのすべてのフィールドも不変でなければならないと思います。Yユーザーを実装可能にすると同時にスレッドセーフにする最良の方法は何ですか? スレッドセーフなメカニズムを実装し、拡張できる抽象クラスですか? 現在、Y実装可能な getter メソッドを備えたインターフェイスですが、もちろんスレッドセーフではありません。
  3. 同時アクセスの観点から、開始/停止メカニズムは正しく実装されていますか?
4

1 に答える 1

1

あなたの問題の核心は、その内容ではなく参照private volatile Y yObj;のみを作成することです。yObjvolatile

後で行うx = yObj.getY();と、結果として理論的にはスレッドセーフではない可能性のある不揮発性変数へのアクセスを要求している可能性があります。

不変yObjにすることは役立つかもしれませんが、それを強制することは困難です。

あなたの開始/停止メカニズムは問題ないように見えますが、私は を使用しAtomicBoolean、同期をドロップして使用するif(active.compareAndSet(false, true) { ...か、同様のものを使用します。

于 2013-07-27T21:46:40.360 に答える