Одновременные чтения с немодифицируемой карты - PullRequest
10 голосов
/ 22 апреля 2011

Если я статически инициализирую карту и устанавливаю ссылку на Collections.unmodifiableMap (Map m). Нужно ли синхронизировать чтение?

private static final Map<String,String> staticMap; 
static{
   Map<String,String> tempMap = new HashMap<String,String>();

   tempMap.put("key 1","value 1");
   tempMap.put("key 2","value 2");
   tempMap.put("key 3","value 3");

   staticMap = Collections.unmodifiableMap(tempMap);
}

Ответы [ 6 ]

10 голосов
/ 22 апреля 2011

Нет, карта, которую вы создаете, эффективно неизменна (поскольку ничто не имеет ссылки на изменяемую резервную карту) и безопасна для одновременного доступа. Если вы хотите получить более четкую гарантию этого, а также упростить создание карты, тип Guava * ImmutableMap предназначен именно для этого вида использования (среди прочего):

private static final ImmutableMap<String, String> staticMap = ImmutableMap.of(
    "key1", "value1",
    "key2", "value2",
    "key3", "value3");
5 голосов
/ 22 апреля 2011

Нет, чтение не изменяет карту, поэтому я бы не стал об этом беспокоиться. Синхронизация вокруг него требует только запись + запись или запись + чтение.

4 голосов
/ 15 марта 2015

Я не согласен с приведенными выше ответами. В реализации карты содержатся энергонезависимые поля (например, HashMap.entrySet. В неизменяемом случае: UnmodifiableMap.keySet, UnmodifiableMap.entrySet и UnmodifiableMap.values). Эти поля лениво инициализируются, поэтому NULL после статического инициализатора. Если один поток затем вызывает entrySet(), это инициализирует поле entrySet. Доступ к этому полю небезопасен из всех других потоков. Поле может быть видно из другого потока в несогласованном состоянии или не отображаться совсем.

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

Это зависит от реализации карты.HashMap, TreeMap и тому подобное имеют чтения, которые не требуют изменений, и это нормально, но реализации, которые отслеживают использование, могут выполнять обновления внутри.

Примером является LinkedHashMap с порядком доступа:

new LinkedHashMap(int initialCapacity, float loadFactor, boolean accessOrder)

Это будет фактически переупорядочивать элементы при каждом чтении, так что итерация по ключам, значениям или записям будет в первом доступе в первом порядке.Еще одна карта, которая может быть изменена - WeakHashMap.

Отличной альтернативой \ будет ImmutableMap, найденный в библиотеке гуавы Google.

3 голосов
/ 22 апреля 2011

Краткий ответ: нет.Вам не нужно блокировать, если нет конфликта чтения-записи.Блокировка возможна только в том случае, если то, чем вы делитесь, может измениться, если оно не изменится, то в основном оно неизменяемое, а неизменяемые считаются поточно-безопасными.

1 голос
/ 29 апреля 2011

Я думаю, что другие уже рассмотрели ответ (да, в случае реализации HashMap). Если вам не всегда нужна карта для создания, вы можете сделать ее ленивой, используя идиому держателя Initialize-On-Demand:

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

public class YourClass {

  // created only if needed, thread-safety still preserved
  private static final class MapHolder {
    private static final Map<String,String> staticMap; 
    static{
      System.out.println("Constructing staticMap");
      Map<String,String> tempMap = new HashMap<String,String>();

      tempMap.put("key 1","value 1");
      tempMap.put("key 2","value 2");
      tempMap.put("key 3","value 3");

      staticMap = Collections.unmodifiableMap(tempMap);
    }
  }

  // use this to actually access the instance 
  public static Map<String,String> mapGetter() {
    return MapHolder.staticMap;
  }

  public static void main(String[] arg) {
    System.out.println("Started, note that staticMap not yet created until...");
    Map<String,String> m = mapGetter();
    System.out.println("we get it: " + m);
  }
}

который напечатает:

Started, note that staticMap not yet created until...
Constructing staticMap
we get it: {key 1=value 1, key 2=value 2, key 3=value 3}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...