java.util.HashMap lock sull'effettivo oggetto HashMap confronta per bloccare l'oggetto che incapsula la HashMap

1

Il seguente Javadoc è uno snippet di documentazione di HashMap . Perché gli autori dovrebbero enfatizzare mettendo un blocco sull'oggetto che incapsula una HashMap? Bloccare sull'oggetto HashMap attuale ha senso.

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.) This is typically accomplished by synchronizing on some object that naturally encapsulates the map. If no such object exists, the map should be "wrapped" using the Collections.synchronizedMap method...

    
posta sij 26.05.2014 - 07:46
fonte

2 risposte

3

L'incapsulamento è necessario qui al fine di limitare l'accesso diretto del codice client ai metodi di% % co_de.

Per quanto riguarda i consigli su quale oggetto utilizzare come blocco, esso ha lo scopo di consentire al codice client di scorrere sulla mappa in modo thread-safe.

Se si intende sincronizzare la propria mappa ma bloccare l'oggetto HashMap effettivo, senza nasconderlo (incapsulandolo), qualsiasi codice che abbia accesso a tale oggetto sarà in grado di invocare i suoi metodi non sincronizzati e interrompere la sincronizzazione. Scopo dell'incapsulamento in questo caso è indicato ulteriormente in javadocs che si riferisce: "per impedire l'accesso non sincronizzato accidentale alla mappa" .

La documentazione si riferisce anche a Collezioni .synchronizedMap come esempio su come ci si aspetta che si sincronizzi:

Returns a synchronized (thread-safe) map backed by the specified map. In order to guarantee serial access, it is critical that all access to the backing map is accomplished through the returned map...

Come vedi, la documentazione di HashMap ribadisce l'importanza ("è fondamentale") per il codice del client che non accede direttamente a "backing map".

Questa documentazione fornisce inoltre un esempio che spiega perché si consiglia di sincronizzarsi sull'oggetto che racchiude:

It is imperative that the user manually synchronize on the returned map when iterating over any of its collection views:

  Map m = Collections.synchronizedMap(new HashMap());
      ...
  Set s = m.keySet();  // Needn't be in synchronized block
      ...
  synchronized (m) {  // Synchronizing on m, not s!
      Iterator i = s.iterator(); // Must be in synchronized block
      while (i.hasNext())
          foo(i.next());
  }

Failure to follow this advice may result in non-deterministic behavior.

Vedete, nell'esempio di codice precedente, se il codice client non avrebbe accesso all'oggetto di blocco "conosciuto per convenzione", sarebbe impossibile sincronizzarlo correttamente: un altro codice potrebbe aver usato un altro blocco per avvolgere l'iterazione che sarebbe portare a un accesso non sincronizzato.

    
risposta data 26.05.2014 - 08:10
fonte
0

Lo capisco dicendo che un modo "facile" è usare i wrapper sincronizzati o rendere la classe che tiene sincronizzata la mappa (cioè usando metodi sincronizzati, che è essenzialmente ciò che fanno i wrapper).

Ma ci sono altri modi, come la sincronizzazione sulla mappa stessa se è privata e finale, usando un oggetto lock separato o usando una ConcurrentMap. Non vorrei sovvertire ciò che viene detto qui e semplicemente applicare i normali schemi di concorrenza.

    
risposta data 26.05.2014 - 10:56
fonte

Leggi altre domande sui tag