我正在閱讀「實踐中的java併發」一書,並在幾頁之後出現一些疑問。與易失性,不可變對象有關的疑問以及它們用於實現同步的疑問
1)具有非前導數據類型的靈活性: 私有易變性Student s; 非易失性數據類型時,volatile的意義何在? (我認爲在這種情況下,只是認爲所有線程都可以看到Strudent對象正在指向哪個線程,而且有可能一個線程A修改了學生的一些內部成員,而這對其他線程是不可見的。 ??)
2) 即使內部成員沒有被聲明爲final,變量是不可變的嗎? 例如:
Class A {
private Set<String> s = new Set();
public A() {
s.add("Moe");
s.add("Larry");
s.add("Curly");
}
}
在課堂上做我們需要設置的最後使它不變或此類仍然是不變的? (因爲即使在這種情況下,我們也不能在創建對象後改變對象的狀態)。
3)書中有一個例子展示瞭如何組合使用volatile和immutable類來獲得同步。在我提出這個問題之前,我還有一個疑問。 假設有這樣一些功能:
private Student s = new Student;
void func() {
s.func2(); // 1
if(s.isPossible()) { //2
s = new Student(); //3
}
}
一個)FUNC2()接取S的內部構件。現在考慮線程A在執行第1行後進入func2,並且線程B在同一時間重新分配新對象。當線程A恢復 它將使用新對象還是舊對象? (假設最初指向內存位置100(舊對象),並且在分配新對象後它開始指向200(新對象) ,則當線程A重新開始時它將訪問地址100或地址200)。 b)如果我使s變得不穩定,它會對上述情況產生什麼影響。
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);
}
}
Accroding到書類 「VolatileCachedFactorizer」 是線程安全的。這是我的推理,爲什麼它是線程安全的(糾正我,如果我錯了。)位置A和位置B是 可疑位置。位置A:由於緩存指向不可變對象,所以任何函數調用都是安全的(對吧?)。
位置B:它可以有兩個問題
一)線程看到緩存不當初始化。在這種情況下不可能作爲不可變對象保證正確初始化(對吧?)。
b)新分配的對象對其他線程不可見。這種情況不可能,因爲緩存是不穩定的(對吧?)。
但它有可能線程調用getFactors()和其他線程B重新分配緩存,在這種情況下,A將繼續看到舊對象
爲什麼不問你3個單獨的問題...... 3個不同的問題? – Raedwald
因爲有4個? ;) – selig
這些都與我有關,如果有人問到這些問題和適當的答案,這對他/她會很有幫助。 – user1875798