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
asを宣言しました。クラスの考え方は、オブジェクトのセッターを呼び出すときに参照値のセット (この例では 1 つだけ) をクラスに提供することです。質問は次のとおりです。volatile
setY(Y)
Y
X
X
x
として宣言しvolatile
、すべてのスレッドの共通の可視性を確保するか、さらに同期する必要がありますか?- アイデアは、クラスのすべてのオブジェクトを
Y
不変にすることです。したがって、そのすべてのフィールドも不変でなければならないと思います。Y
ユーザーを実装可能にすると同時にスレッドセーフにする最良の方法は何ですか? スレッドセーフなメカニズムを実装し、拡張できる抽象クラスですか? 現在、Y
実装可能な getter メソッドを備えたインターフェイスですが、もちろんスレッドセーフではありません。 - 同時アクセスの観点から、開始/停止メカニズムは正しく実装されていますか?