2014-02-13 27 views
2

是否可以使用volatile變量來允許一致的只寫同步?是否可以使用volatile變量來允許一致的只寫同步?

這是代碼:

public class Controller { 

    Container cont = new Container(); 
    ... 

    public Object get(){ 
     if(!cont.isLocked()){ 
      return cont.getObject(); //many threads can read at the same time 
     } 
     else synchronized(cont){ 
      return cont.getObject(); //threads wait until write is finished 
     } 
    } 

    public void set(Object o){ 
     synchronized(cont){ 
      cont.lock(); 
      cont.setObject(o); 
      cont.unlock(); 
     } 
    } 
} 

public class Container { 
    private volatile boolean lock = false; 
    private Object data; 

    public Container(){ 
      } 

    public void lock() { 
     lock = true; 
    } 

    public void unlock() { 
     lock = false; 
    } 

    public boolean isLocked() { 
     return lock; 
    } 

    public void setObject(Object o) { 
     data = o; 
    } 

    public Object getObject() { 
     return data; 
    } 
} 

一下行不行,還是會打破它,你覺得呢?

+1

這對我來說很好。但是如果你想確定,你可以通過在'setObject'和'getObject'中引入延遲來測試它。再加上一些明智的調試信息。 +1生產SSCCE。 –

回答

5

它可能會破壞。執行的例子:

  • T1:if(!cont.isLocked())返回true
  • T2:set(someObject)
  • T1:return cont.getObject();返回舊版本

更糟糕的是,因爲你沒有一個適當的happens-在T2與T1之間的關係之前,cont.getObject()可能會返回對由T2創建的新對象的引用,但指向不一致/未完全構造的對象。

您有一個典型的check-then-act問題。

爲什麼你不使用一個易變的引用到你的對象?

public class Controller { 

    private volatile Object obj = new Object(); 

    public Object get(){ return obj; } 
    public void set(Object o){ obj = o; } 
} 

這將是線程安全的。

+0

所以'對象數據'也應該是不穩定的吧? – Marcus

+1

這很可能是不夠的 - 但是你應該解釋你真正的目標,因爲你的例子是不必要的複雜性 - 因此無論您的實際使用情況下,有你有沒有提及或你應該做夜類簡單了很多額外的約束。 – assylias

+0

你真的認爲它可以做得更簡單嗎?我的意思是,我不能只同步上'對象data',這會破壞非同步的目的讀取... – Marcus

相關問題