如何確保initialize()方法只被調用一次?下面是我想重構使用AtomicBoolean的線程不安全版本。 所有我想要的是初始化()只調用一次如何使用AtomicBoolean實現此目的?
if (!initialized)
{
initialize();
initialized = true;
}
如何確保initialize()方法只被調用一次?下面是我想重構使用AtomicBoolean的線程不安全版本。 所有我想要的是初始化()只調用一次如何使用AtomicBoolean實現此目的?
if (!initialized)
{
initialize();
initialized = true;
}
private final AtomicBoolean initialized = new AtomicBoolean(false);
//in some method:
if(!initialized.getAndSet(true))
{
initialize();
}
我不認爲這是安全的。它_will_保證initialize()只被調用一次,但是第二個線程在getAndSet()之前不會被延遲,直到第一個線程完成初始化。 – 2011-05-12 22:33:31
...因此,它會相信對象將被初始化,但事實並非如此。此解決方案無效,不應使用。 – JVerstry 2011-05-14 21:13:21
一個原子布爾不會被足夠多的適合你,因爲輸入代碼塊中的第二個線程將throught下降,即使有沒有初始化還沒有完成。試試這個,這將阻止第二,平行只有當第尚未完成,而且會非常快,當初始化完成:
volatile boolean initialized = false;
private final Object LOCK = new Object();
public void ensureInitialized() {
if(!initialized) {
synchronized(LOCK) {
if(!initialized) {
initialize();
initialized = true;
}
}
}
}
這也被稱爲雙重檢查鎖定ideom,這它的做法是正確的。
其實,你並不需要一個原子布爾用下面的代碼:
public class YourClass() {
volatile boolean initialized = false;
public void ensureInitialized() {
if (initialized) return;
synchronized(this) {
if (!initialized) {
initialize();
initialized = true;
}
}
}
// The code of this method could be moved
// into the synchronized statement above
public void initialize() { ... };
}
由於初始化代碼只會被調用一次,沒有真正的好處是用一個的AtomicBoolean。
在'this'上同步可能需要更多時間,但創建AtomicBoolean也是如此。這兩個操作只發生一次。
總體而言,此解決方案使用較少的內存。
編輯:更新的解決方案
當然,'初始化()'完成之前的代碼可能會退出。 – 2011-05-12 21:33:22
關鍵是使用'AtomicBoolean',它允許您在沒有代價高昂的同步的情況下執行原子更新(它使用CPU CAS操作和volatile變量)。 – 2011-05-12 21:34:58