スレッドセーフであるかどうかを確認しようとしています。私はそうだと信じていますが、最近誰かがこのメソッドのスレッドの安全性を疑問視しました。スレッドの安全性を理解する
のは、私は私たちに次のインタフェースを実装するクラス与えるいくつかの工場FactoryA
あるとしましょう:だから
public abstract class MyFactory {
private ObjectA object;
public void init(ObjectA object){
_object = object;
}
}
を、私たちは今、
public class FactoryA extends MyFactory {
static final createFactoryClass(String name) {
// ...ignorning safety checks for brevity
return MY_MAP.get(name).newInstance();
}
}
のように、私は別で、いくつかの方法を持っている何かを持っていますファクトリーを取り上げ、可能なクラスの地図を返すクラス:
public class OtherClass {
private static FactoryA _factory = new FactoryA();
private static final Map<String, SomeClass> MY_MAP = new ImmutableMap.Builder<String, MyClass>()
.put("foo", _factory.createFactoryClass("foo"));
private SomeObject myMethod(ObjectA objectA, SomeObject someObject) {
MY_MAP.get(someObject.getString()).init(objectA);
}
}
質問はinit
メソッドがスレッドセーフであるかどうかです。マップは1回しか初期化されないため、2つのスレッドが異なるObjectA
を呼び出すと、不変構造に格納されていても間違ったクラスが間違って使用される可能性がありますObjectA
?
次のようにしてこの問題を解決できますか?変数、すなわち、次の例のように、共有されるオブジェクトへの参照でない限り
private static synchronized myMethod(...) {}
コード内では、クロスクラスと型の不一致を参照しているので、少し混乱します。しかし、私は本当の疑問はあなたの 'init'メソッドでやっていることにあると思いますか? – Xerillio
あなたの 'MyFactory.init'メソッドは、何もしないので完全にスレッドセーフです。 –
'createFactoryClass()'もスレッドセーフであるようです。地図を一度初期化したら、もう一度書き込んではいけません。ここでの条件は、まだ見えるようにしなければならないということです。それを 'final'に割り当てることは罰金であり、' volatile'と 'synchronized'のようにマップ(そしてすべての書き込み)を見えるようにします。 C.f。 ["安全な出版物"](http://stackoverflow.com/questions/801993/java-multi-threading-safe-publication) – markspace