2011-03-28 69 views
0

我有一個類SomeMutableData使用公共clone()方法。我想確保沒有線程看到不一致的狀態(假設實例將僅使用持有者傳遞)。我假設使用同步是最安全的可能性,對吧?任意可複製數據的線程安全持有者

public final class ThreadSafeHolder { 
    public ThreadSafeHolder(SomeMutableData data) { 
     storeData(data); 
    } 

    public synchronized SomeMutableData cloneData() { 
     return data.clone(); 
    } 
    public synchronized void storeData(SomeMutableData data) { 
     this.data = data.clone(); 
    } 

    private SomeMutableData data; 
} 

以下與第一種方法一樣安全嗎?

public final class ThreadSafeHolder2 { 
    public ThreadSafeHolder2(SomeMutableData data) { 
     storeData(data); 
    } 

    public SomeMutableData cloneData() { 
     return data.get().clone(); 
    } 
    public void storeData(SomeMutableData data) { 
     this.data.set(data.clone()); 
    } 

    private final AtomicReference<SomeMutableData> data 
     = new AtomicReference<SomeMutableData>(); 
} 

回答

2

由於clone()比同步更昂貴,從性能的角度來看,它並不重要。

然而,第二個例子是線程安全並且邊緣更快。

唯一的區別就是第一個例子你可以做到這一點。 (不管你是否喜歡這個;)

synchronized(theHolder) { 
    SomeMutableData smd = theHolder.cloneData(); 
    smd.updateIt(); 
    theHolder.storeData(smd); 
} 

順便說一句:我不認爲持有人應擴大它包裝的類型。

編輯:更友善的GC方法是使用以下方法。您可以編寫copyFrom(),以便不會創建設置或獲取數據的對象。

public final class ThreadSafeHolder { 
    private final SomeMutableData data = new SomeMutableData(); 

    public ThreadSafeHolder(SomeMutableData data) { 
     copyFrom(data); 
    } 

    public synchronized void copyTo(SomeMutableData data) { 
     data.copyFrom(this.data); 
    } 

    public synchronized void copyFrom(SomeMutableData data) { 
     this.data.copyFrom(data); 
    } 
} 
+1

*「我不認爲持有人應該擴展它正在包裝的類型。」 - - 我也不是!這不是我,它是日食... – maaartinus 2011-03-28 16:51:52