Насколько безопасно использование потока synchronizedMap? - PullRequest
3 голосов
/ 13 апреля 2011

У меня есть одноэлементный класс, у которого есть карта, к которой могут обращаться несколько потоков одновременно.Может кто-нибудь проверить код ниже и сказать мне, если его поток безопасен?(примечание: я не планирую использовать ConcurrentHashMap, и метод printMap вызывается редко).

    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 не должны иметь блок «synchronized», так как я использую synchronizedMap

  2. printMap должен иметь синхронизированный блок, поскольку Javadoc для говорит, что мы должны синхронизировать экземпляр Map перед каждой итерацией.http://download.oracle.com/javase/1.5.0/docs/api/java/util/Collections.html#synchronizedMap%28java.util.Map%29

Любая помощь приветствуется.

Ответы [ 3 ]

4 голосов
/ 13 апреля 2011

Да, все в порядке.Ключевым моментом является то, что пока вы выполняете итерации, ничто не сможет изменить карту, потому что cache.put все равно закончится синхронизацией на cache.

Лично Я бы лучшесделайте это явным, используя «нормальную» хэш-карту и синхронизировав на одном и том же объекте (будь то карта или что-то еще) из всех трех методов, - но то, что у вас есть, должно быть в порядке.можно использовать ConcurrentHashMap для начала. Стоит хотя бы взглянуть на это.)

0 голосов
/ 13 апреля 2011

Да, этот класс является поточно-ориентированным.

Хотя обратите внимание, что даже потокобезопасный класс требует безопасной публикации для действительно безопасного использования (без безопасной публикации ничто не гарантирует, что другие потоки не смогут увидеть cache в неинициализированном состоянии, т.е. null).

Но в этом случае вы можете устранить необходимость в безопасной публикации, сделав свой класс неизменным (ключевое слово final гарантирует, что другие потоки не смогут увидеть null в cache):

private final Map<String,String>  cache = Collections.synchronizedMap( new LinkedHashMap<String,String>()); 
0 голосов
/ 13 апреля 2011

Да, это потокобезопасно.Каждый доступ к кешу синхронизируется (с помощью synchronizedMap для получения и установки и с помощью явного блока синхронизации для printMap)

...