ConcurrentHashMap non acquisisce il lock sul this (ovvero sulla istanza del ConcurrentHashMap), come invece fanno es. Vector e Hashtable.
In Vector/Hashtable i loro metodi acquisiscono il lock sul this e quindi se tu sfrutti la tecnica del "client-side locking" e acquisisci il lock sulla istanza della collezione con un synchronized(obj) (per fare tipicamente operazioni "composte" tipo: leggi .. fai qualcosa ... scrivi) allora hai la garanzia della "atomicità" e anche che nessun altro thread può compiere operazioni direttamente sulla collezione, visto che il lock usato dalla collezione è lo stesso che usi tu.
Con ConcurrentHashMap non è così, i lock sono interni, nascosti, e ce n'è più di uno (fino a Java 7 la implementazione di ConcurrentHashMap usava la tecnica del "lock striping" mentre in Java 8 se non sbaglio la implementazione è cambiata abbastanza radicalmente).
In sostanza con ConcurrentHashMap la tecnica del client-side locking NON funziona in generale per fare operazioni "composte". Proprio per questo motivo in ConcurrentHashMap hanno aggiunto operazioni tipo putIfAbsent e il remove(Object key, Object value) (e i due replace) perché con il client-side locking non sarebbero possibili in modo safe.
Se tu in tutti (e ripeto tutti) i punti dove usi quell'oggetto ConcurrentHashMap sfrutti il client-side locking e acquisisci il lock sulla mappa, allora può funzionare perché in sostanza stai imponendo tu un "protocollo" di sincronizzazione ben preciso e che deve appunto essere consistente e comune. Solo che se fai così ... imponi una forte "serializzazione" degli accessi alla mappa e quindi tutti i benefici della alta concorrenza di ConcurrentHashMap vanno a farsi friggere ....
Morale della favola: rivedi bene il tutto (alla luce di quanto ho detto).![]()



Rispondi quotando