私は本「実際のJava並行性」を読んでいて、数ページ後にいくつかの疑問が生じました。
1) 非プリミティブなデータ型を持つ voltile : private volatile Student s; 非プリミティブデータ型が付属する場合、揮発性の重要性は何ですか? (この場合、すべてのスレッドに確実に表示されるのは、Strudent オブジェクトが現在指しているものであり、1 つのスレッド A が学生の内部メンバーを変更し、他のスレッドには表示されない可能性があると考えているだけだと思います。私は正しいですか? ??)
2) 内部メンバーが final として宣言されていなくても、変数は不変にできますか?? 例えば :
Class A {
private Set<String> s = new Set();
public A() {
s.add("Moe");
s.add("Larry");
s.add("Curly");
}
}
このクラスでは Set を final にして不変にする必要がありますか、それともこのクラスはまだ不変ですか? (この場合でも、作成後にオブジェクトの状態を変更できないため)。
3)本には、揮発性クラスと不変クラスを組み合わせて使用 して同期を取得する方法を示す1つの例があります。その質問をする前に、もう 1 つ疑問があります。次のような関数があるとします。
private Student s = new Student;
void func() {
s.func2(); // 1
if(s.isPossible()) { //2
s = new Student(); //3
}
}
a)func2() s の内部メンバーにアクセスします。ここで、スレッド A が 1 行目を実行した後に func2 に入り、スレッド B が新しいオブジェクトで s を同時に再割り当てするとします。スレッド A が再開すると、新しいオブジェクトまたは古いオブジェクトを使用しますか? ( s が最初にメモリ位置 100 (古いオブジェクト) を指し、新しいオブジェクトが割り当てられた後、200 (新しいオブジェクト) を指し始め、スレッド A が再開すると、アドレス 100 またはアドレス 200 にアクセスするとします)。
b) s を volatile にすると、上記のケースに違いはありますか。
4.) そしてこれが最後のものです
@Immutable
class OneValueCache {
private final BigInteger lastNumber;
private final BigInteger[] lastFactors;
public OneValueCache(BigInteger i,
BigInteger[] factors) {
lastNumber = i;
lastFactors = Arrays.copyOf(factors, factors.length);
}
public BigInteger[] getFactors(BigInteger i) {
if (lastNumber == null || !lastNumber.equals(i))
return null;
else
return Arrays.copyOf(lastFactors, lastFactors.length);
}
}
@ThreadSafe
public class VolatileCachedFactorizer implements Servlet {
private volatile OneValueCache cache = new OneValueCache(null, null);
public void service(ServletRequest req, ServletResponse resp) {
BigInteger i = extractFromRequest(req);
BigInteger[] factors = cache.getFactors(i); // Position A
if (factors == null) {
factors = factor(i);
cache = new OneValueCache(i, factors); // Position B
}
encodeIntoResponse(resp, factors);
}
}
book クラス "VolatileCachedFactorizer" への準拠はスレッドセーフです。スレッドセーフである理由は次のとおりです (間違っている場合は訂正してください)。Positin A と Position B は疑わしい位置です。
位置 A : キャッシュが不変オブジェクトを指しているため、関数呼び出しは安全です (そうですか?)。
ポジション B : 2 つの問題が発生する可能性があります
a) スレッドは、キャッシュが不適切に初期化されていることを確認します。不変オブジェクトは適切に初期化されることが保証されているため、この場合は不可能です (そうですか?)。
b) 他のスレッドからは見えない、新しく割り当てられたオブジェクト。キャッシュは揮発性であるため、このケースは不可能です (そうですか?)。
しかし、スレッド A が getFactors() を呼び出し、他のスレッド B が cache を再割り当てする可能性があります。この場合、A は引き続き古いオブジェクトを参照します (そうですか?)