2011-06-29 87 views
1

我有一個像下面的類,我想知道,這將是線程安全的,或者主線程和Loader線程可能有自己的mCache副本,因此get(..)方法無法從緩存中檢索任何內容,因爲它是在加載程序線程中添加的?我需要標記這個volatile實例變量和線程

謝謝!

public class StackExample 
{ 
    private final ConcurrentHashMap<String, SoftReference<Bitmap>> mCache = new ConcurrentHashMap<String, SoftReference<Bitmap>>(); 

    private addToCache(String key, Bitmap bitmap) 
    { 
     mCache.put(key, bitmap); 
    } 

    private Bitmap getBitmap(String key) 
    { 
     if(mCache.contains(key)) 
     { 
      return mCache.get(key); 
     } 
     else 
     { 
      //add to loading queue 
     } 
    } 

    private class Loader extends Thread 
    { 
     @Override 
     public void run() 
     { 
      ...//check loading queue and load some images here 
      mCache.put(keyString, new SoftReference<Bitmap>(loadedBitmap)); 
     } 
    } 
} 
+0

您將只對所有線程都具有唯一的* mCache *,但您的代碼仍然沒有正確同步。你*可以*輸入兩次(或多於)* *添加到加載隊列*你的代碼的一部分爲同一個*鍵*雖然從你的例子中並不完全清楚* getBitmap *從哪裏調用(它顯然是私有的!?)。 – SyntaxT3rr0r

+0

btw +1對你的問題和羞恥的人誰upvoted Jon Skeet的一個線路的答案,也沒有upvoting很好的問題。 – SyntaxT3rr0r

+0

謝謝!是的,只是一個簡單的例子,我知道你的意思是關於get方法:) – Dori

回答

4

變量是final的,所以它在構造函數(在這種情況下爲空)返回之前對所有線程都是可見的。

+0

它是否可變無關緊要?最終的領域是否不會受到持有自己副本的線索的影響? – Dori

+1

@Dori:你認爲會被複制什麼? 'ConcurrentHashMap'是可變的,但是*設計*被多個線程使用而不鎖定。 –

+0

對不起,我的印象可能是錯誤的,即所有變量都能夠被使用它們的每個線程保留爲本地副本,導致線程可能無法查看另一個線程對該變量所做的更改。在某些情況下,volatile關鍵字可以防止這種情況發生,但不會停止交錯操作。我也認爲同步停止交錯操作,但我不確定它對變量的本地複製/緩存有什麼影響 - 當sycnronised塊啓動/退出變量是否刷新/推送到主內存? – Dori

0

volatile表示每個線程都不會保留字段值的緩存。如果您能夠寫入mCache字段,那麼如果您想確保另一個線程在由另一個線程設置後立即讀取該字段時獲得了新值,則可以聲明該字段不穩定。

+0

從上面我認爲這不適合的情況下,因爲該字段只是一個參考和最終 – Dori

+0

確切。沒有理由宣佈它不穩定時,它不能改變 –