只是爲了確保我理解java實踐中呈現的概念。java中的初始化安全性
可以說我有以下程序:
public class Stuff{
private int x;
public Stuff(int x){
this.x=x;
}
public int getX(){return x;}
}
public class UseStuff(){
private Stuff s;
public void makeStuff(int x){
s=new Stuff(x);
}
public int useStuff(){
return s.getX();
}
}
如果我讓多個線程使用此代碼打球,那麼我不僅麻煩,因爲S可能會發生被指向如果兩個或更多的多個實例線程正在進入makeStuff方法,但即使只有一個線程創建了一個新的Stuff,那麼剛剛進入useStuff的其他線程可以通過其構造函數返回值0(預定義的int值)或分配給「x」的值。
這一切都取決於構造函數是否已完成初始化x。
所以在這一點上,爲了使線程安全,我必須做一件事,然後我可以從兩種不同的方式中選擇。
首先,我必須make makeStuff()原子,所以「s」將一次指向一個對象。
然後,我要麼使useStuff同步,以確保我只能在其構造函數完成構建後才能返回Stuff對象x var,或者我可以使Stuff的x最終,並由此JMM確保x的值只有在初始化後纔可見。
我瞭解最終字段在併發和JMM上下文中的重要性嗎?
假設UseStuff的實例在線程之間共享,那麼:no,s將始終指向一次只有一個實例。你的問題是你不確定它是哪個實例,因爲多個線程可能會覆蓋該引用。通過將其設置爲final,您可以確保在UseStuff初始化時設置了引用s,並且在任何線程中都不會更改它。 – Gergely 2015-02-23 21:23:04
對不起,只是注意到你想做x最後。所以在這種情況下,你要保證一旦創建了一個Stuff實例,它的字段x就再也不會被改變了。在這種情況下,字段仍然可以被新的Stuff覆蓋,但是至少可以確定Stuff的特定實例永遠不會有任何線程更改其x。 – Gergely 2015-02-23 21:29:23