Zurück zur Nebenläufigkeit. Inzwischen ist klar, dass für die double checked locking
zu arbeiten die Variable muss als volatile
deklariert werden. Aber was ist dann, wenn eine doppelt überprüfte Verriegelung wie unten verwendet wird.Double checked locking mit regulärer HashMap
class Test<A, B> {
private final Map<A, B> map = new HashMap<>();
public B fetch(A key, Function<A, B> loader) {
B value = map.get(key);
if (value == null) {
synchronized (this) {
value = map.get(key);
if (value == null) {
value = loader.apply(key);
map.put(key, value);
}
}
}
return value;
}
}
Warum muss es wirklich ein ConcurrentHashMap und keine regulären HashMap sein? Alle Kartenänderungen werden innerhalb des Blocks synchronized
durchgeführt, und der Code verwendet keine Iteratoren, daher sollte es technisch keine Probleme mit "gleichzeitiger Änderung" geben.
Bitte vermeiden Sie was auf die Verwendung von putIfAbsent
/computeIfAbsent
als ich über das Konzept gefragt bin und nicht die Verwendung von API :), es sei denn mit dieser API trägt zum HashMap
vs ConcurrentHashMap
Thema.
-Update 2016-12-30
Diese Frage durch einen Kommentar unten von Holger "HashMap.get
die Struktur ändern, aber Ihr Aufruf von put
nicht tut beantwortet wurde. Da es ein Aufruf von get
außen des synchronisierten Blocks kann er einen unvollständigen Zustand einer put
Operation gleichzeitig sehen. " Vielen Dank!
Da die Karte wird nach einigen Puts Größe ändern und es wird sicherlich Ihre entsperrt bekommen Anrufe zu brechen. –
putIfAbsent/computeIfAbsent sind atomare und nicht nur für die Bequemlichkeit –
Thomas, könnten Sie bitte auf "Break Get Calls" bitte. Ich habe nur explizite Verweise auf gleichzeitige Puts und Iteratoren in den Dokumenten gefunden und bei der Suche nach "hashmap concurrent access" –