È necessario sincronizzare una chiamata a una funzione thread-safe?
-
08-07-2019 - |
Domanda
Se sto usando ConcurrentHashMap (dove il put è thread sicuro) e fornisco una funzione pubblica myPut che usa il put ConcurrentHashMap - devo sincronizzare la mia funzione?
significato: dovrebbe essere sincronizzato?
ConcurrentHashMap map;
public void myPut(int something) {
this.map.put(something);
}
Soluzione
Utilità di concorrenza come ConcurrentHashMap sono progettate in modo tale da non dover essere sincronizzate: gestiranno internamente un accesso sicuro ai thread.
Ciò che Tom dice è vero, è necessario pensare al potenziale del cambiamento della mappa per cambiare. Se il riferimento in realtà non cambia, in pratica lo farai qui: la sincronizzazione interna di ConcurrentHashMap - e in effetti java.util.concurrentlibrary in generale - garantisce che gli oggetti messo nella mappa sono tranquillamente pubblicati su altri thread. Ma concordo sul fatto che anche in questo caso, è buona norma decidere se il riferimento può cambiare o meno, e quindi dichiararlo esplicitamente nel codice ('final' se non può; qualcosa come 'volatile' o un AtomicReference se può).
Altri suggerimenti
Poiché il riferimento map
non è dichiarato final
, potrebbe essere modificato. Pertanto, esiste un potenziale bug di threading qui.
Se si suppone che map
sia un riferimento modificabile, sarà necessario fare ancora un po 'di lavoro. Altrimenti usa final
. In effetti, usa final
ogni volta che puoi, anche se è "più facile" non farlo. " final
è il nuovo [vecchio] privato
. " Probabilmente vuoi rendere map
privato
e anche generico.
Se usi una ConcurrentHashMap non dovresti sincronizzare 'put' ma ciò non significa che i tuoi 'put' verranno chiamati uno alla volta. Questo dipende dal livello di concorrenza della tua mappa ...
Quindi devi sapere cosa vuoi.
BTW dai un'occhiata alla ConcurrentHashTable Javadoc, tutto è ben spiegato ...
-Patrick
Dipende.
Quando scrivi le classi per gli oggetti che verranno utilizzati da più thread, l'intero gioco cambia. Devi capire quali risultati stai cercando di ottenere se speri di fornire garanzie sulla sicurezza dei thread.
In questo caso, se questo è l'unico metodo nella tua classe, non ha senso sincronizzare l'accesso a questo metodo. Ma non sarà l'unico metodo, perché renderebbe la classe abbastanza inutile.
Devi sincronizzare questo metodo solo se devi farlo per rendere sicuro il thread della classe per altri motivi - a quel punto, potresti voler chiederti se vale l'overhead di un ConcurrentHashMap
.
No.
Puoi chiamare myPut più volte contemporaneamente.
Il put verrà chiamato uno alla volta, perché l'accesso alla HashTable deve essere uno alla volta. (vedi anche la scrittura simultanea in una memoria condivisa)