Вопрос по java, hashmap, multithreading, concurrency – Безопасно ли получать значения из java.util.HashMap из нескольких потоков (без изменений)?

120

Существует случай, когда карта будет построена, и после ее инициализации она никогда не будет изменена снова. Однако к нему можно будет получить доступ (только через get (key)) из нескольких потоков. Безопасно ли использоватьjava.util.HashMap в этом случае?

(В настоящее время я счастливо используюjava.util.concurrent.ConcurrentHashMapи не имеют никакой необходимости улучшать производительность, но мне просто любопытно, еслиHashMap было бы достаточно. Следовательно, этот вопросnot & quot; Какой я должен использовать? & quot; и это не вопрос производительности. Скорее, вопрос «Будет ли это безопасно?»

Error: User Rate Limit Exceeded Heath Borders
Error: User Rate Limit Exceededhappens-before отношения, но не использует такие термины, как «обновления памяти». Вы должны уточнить, предпочтительно используя терминологию из JLS. BeeOnRope
@Heath Границы, если экземпляр a был статически инициализирован неизменяемым HashMap, он должен быть безопасным для одновременного чтения (так как другие потоки не могли пропустить обновления, так как не было обновлений), верно? kaqqao
Error: User Rate Limit ExceededClassLoader, Это само по себе стоит отдельного вопроса. Я по-прежнему явно синхронизирую его и профилирую, чтобы убедиться, что он вызывает реальные проблемы с производительностью. Heath Borders
@ Дэйв - я полагаю, что вы не ищете ответ после 8 лет, но, к сведению, основная путаница почти во всех ответах заключается в том, что они сосредоточены наthe actions you take on the map objectError: User Rate Limit Exceededhow you publish the reference кMap, который вы не объяснили. Если вы не делаете это безопасно, это небезопасно. Если вы делаете это безопасно,it isError: User Rate Limit Exceeded BeeOnRope

Ваш Ответ

11   ответов
9

Error: User Rate Limit ExceededthinkError: User Rate Limit Exceeded
Error: User Rate Limit ExceededHashMap JavadocError: User Rate Limit ExceededNote that this implementation is not synchronized. If multiple threads access a hash map concurrently, and at least one of the threads modifies the map structurally, it must be synchronized externally.
Error: User Rate Limit Exceeded
8

Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded Dave L.
Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded Dave L.
Error: User Rate Limit ExceededisError: User Rate Limit Exceeded
70

Error: User Rate Limit Exceeded Dave L.
Error: User Rate Limit ExceededanswerError: User Rate Limit Exceededsafe publicationError: User Rate Limit Exceeded
10

Note that this implementation is not synchronized. If multiple threads access a hash map concurrently, and at least one of the threads modifies the map structurally, it must be synchronized externally. (A structural modification is any operation that adds or deletes one or more mappings; merely changing the value associated with a key that an instance already contains is not a structural modification.)

Error: User Rate Limit Exceeded Dave L.
Error: User Rate Limit Exceeded
4

Error: User Rate Limit ExceededError: User Rate Limit ExceededError: User Rate Limit Exceeded

... Under the new memory model, there is something similar to a happens-before relationship between the write of a final field in a constructor and the initial load of a shared reference to that object in another thread. ...

Error: User Rate Limit ExceededonlyError: User Rate Limit Exceededsafely publishedError: User Rate Limit Exceeded
Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded
34

Если у вас запущены другие потоки, они могут не увидеть обновленную копию HashMap, если в текущий поток не записана память. Запись в память происходит посредством использования синхронизированных или изменчивых ключевых слов или с использованием некоторых конструкций параллелизма Java.

Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded Dave L.
1

Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded Dave L.
0

public static final HashMap<String, String> map = new HashMap<>();
static {
  map.put("A","A");

}

class Foo {
  volatile HashMap<String, String> map;
  public void init() {
    final HashMap<String, String> tmp = new HashMap<>();
    tmp.put("A","A");
    // writing to volatile has to be after the modification of the map
    this.map = tmp;
  }
}

0

Error: User Rate Limit Exceeded

Error: User Rate Limit Exceeded

Error: User Rate Limit Exceeded

Error: User Rate Limit Exceeded

Error: User Rate Limit Exceeded Dave L.
31

if and only ifHashMap являетсяsafely publishedHashMap сам,safe publication

HashMapHashMap

class SomeClass {
   public static HashMap<Object, Object> MAP;

   public synchronized static setMap(HashMap<Object, Object> m) {
     MAP = m;
   }
}

setMap()SomeClass.MAP

HashMap<Object,Object> map = SomeClass.MAP;
if (map != null) {
  .. use the map
} else {
  .. some default behavior
}

Этоnot safehappens-beforeSomeObject.MAPanything.

happens-beforewriting of the referenceHashMappublication тот[1]:

Exchange the reference through a properly locked field (JLS 17.4.5) Use static initializer to do the initializing stores (JLS 12.4) Exchange the reference via a volatile field (JLS 17.4.5), or as the consequence of this rule, via the AtomicX classes Initialize the value into a final field (JLS 17.5).

MAP

public static volatile HashMap<Object, Object> MAP;

non-nullhappens-beforeMAP

finalMAPneedMAPstatic final HashMap<>

inherently immutablefinal

You already can create the object that will be assigned at the moment of declarationa: just use a final field (including static final for static members). You want to assign the object later, after the reference is already visible: use a volatile fieldb.

static finalfinalmostc.

volatileHashMapHashMap

.

.

a

bsynchronizedAtomicReference

youfinal

never modify HashMapError: User Rate Limit Exceededstate of the map objectError: User Rate Limit Exceeded
Error: User Rate Limit ExceededHashMapError: User Rate Limit Exceededright in the documentationError: User Rate Limit ExceededIf multiple threads access a hash map concurrently, and at least one of the threads modifies the map structurally, it must be synchronized externally. (A structural modification is any operation that adds or deletes one or more mappings; merely changing the value associated with a key that an instance already contains is not a structural modification.)
Error: User Rate Limit ExceededHashMapError: User Rate Limit ExceededHashMapError: User Rate Limit ExceededMapError: User Rate Limit ExceededHashMapError: User Rate Limit Exceeded
Error: User Rate Limit ExceededwritesError: User Rate Limit Exceededget()Error: User Rate Limit ExceededLinkedHashMapError: User Rate Limit Exceeded
Error: User Rate Limit ExceededconstError: User Rate Limit ExceededconstError: User Rate Limit Exceededin generalError: User Rate Limit ExceededLinkedHashMapError: User Rate Limit ExceededgetError: User Rate Limit Exceeded
3

Collections.unmodifiableMap(originalMap)

Error: User Rate Limit Exceeded Dave L.

Похожие вопросы