2011-04-13 93 views
3

我有一個singleton類,它有一個可以被多個線程同時訪問的地圖。有人可以檢查下面的代碼,並告訴我它的線程是否安全? (注:我不打算使用的ConcurrentHashMap和printMap方法被調用只有很少。)synchronizedMap線程的這種用法是否安全?

public class MySingleton{ 

     private Map<String,String> cache = Collections.synchronizedMap(
new LinkedHashMap<String,String>()); 

     public String getValue(String key){ 
     return cache.get(key) 
     } 

     public void setValue(String key, String value){ 
     cache.put(key, value); 
     } 

     public void printMap(){ 
      synchronized(cache){ 

       for(Entry<String,String> entry: cache.entrySet()){ 
        println('key: '+entry.getKey()+', value: ' + value); 

       } 
      } 

     } 
    } 

我的測試工作......但我懷疑如果這個代碼是不夠好,被稱爲「線安全'。

點了,我認爲:

  1. 的readValue和putValue方法並不需要有一個「同步」塊,因爲我使用的是synchronizedMap

  2. printMap應該有同步塊,因爲javadoc表示我們應該在每次迭代之前同步Map實例。 http://download.oracle.com/javase/1.5.0/docs/api/java/util/Collections.html#synchronizedMap%28java.util.Map%29

任何幫助表示讚賞。

+0

在這裏是有點挑剔,但那個班真的是單身人士嗎? – DaveH 2011-04-13 12:19:10

+0

是的,它的春天豆 – rk2010 2011-04-13 12:28:30

+0

行 - 只是檢查... :) – DaveH 2011-04-13 12:32:52

回答

4

是的,沒關係。關鍵是,當你迭代時,沒有東西可以修改地圖,因爲cache.put無論如何都會最終同步到cache

個人我寧願通過使用「正常」散列映射並同步來自所有三種方法的同一對象(不管是地圖還是其他方法) - 但是你應該沒問題。

(或者,您也可以使用ConcurrentHashMap開始。這是值得至少在看那個。)

+1

實際上,當我查看代碼時,cache.put正在同步一個名爲mutex的內部對象。不是本身。有什麼想法嗎? – rk2010 2011-04-13 12:23:09

+0

@ rk2010:看看構造函數:'mutex = this;' – 2011-04-13 12:23:55

+1

我真的很喜歡你的正常哈希映射想法......! – rk2010 2011-04-13 12:24:29

0

是的,它是線程安全的。對緩存的每次訪問都是同步的(通過synchronizedMap獲取和設置,並通過printMap的顯式同步塊)

0

是的,該類是線程安全的。

,即使是線程安全類需要 安全出版物真正做到安全使用

雖然說明(無安全出版物沒有保證其他線程無法看到未初始化狀態cache,即null)。

但在這種情況下,你可以通過你的類不可變的(final關鍵字保證nullcache其他線程無法看到)消除安全出版物需要:

private final Map<String,String> cache = Collections.synchronizedMap(new LinkedHashMap<String,String>());