Code: Select all
ConcurrentDictionary d;
// Add
var list = d.GetOrAdd ("key", x => new List ());
lock (list) {
list.Add ("value to add");
}
// Remove
if (d.TryGetValue ("key", out var list)) {
lock (list) {
list.Remove ("value to remove");
}
}
Code: Select all
if (d.TryGetValue ("key", out var list)) {
lock (list) {
if (list.Remove ("value to remove") && list.Count == 0) {
d.TryRemove ("key", out _);
}
}
}
- A: Liste abrufen
- B: Liste abrufen
- B: sperren, aus Liste entfernen< /li>
B: Liste ist leer, Schlüssel löschen, entsperren - A: Sperren, zur Liste hinzufügen, entsperren
Soweit ich das beurteilen kann, würde eine Lösung normalerweise mithilfe von Vergleichs- und Austauschoperationen und dem Ersetzen der Liste durch z. B. gefunden werden. ein unveränderliches Array, das dann vollständig ersetzt wird. Da ConcurrentDictionary jedoch kein TryRemove mit einem erwarteten-Wert zum Vergleich anbietet, verstehe ich nicht ganz, wie das geht. Möglicherweise gibt es eine zweistufige Lösung?
Die Verwendung des out-Parameters von TryRemove zum erneuten Hinzufügen von Werten nach dem Entfernen (um Race-Fälle zu beheben) ist nicht möglich - Das Wörterbuch wäre kurzzeitig in einem inkonsistenten Zustand.
Auf dieser Website gibt es viele Fragen zu ähnlichen Szenarien, aber die meisten davon weisen triviale Fehler auf oder werden nicht entfernt leere Einträge. Es gibt diese sehr verwandte Frage, die fragt, ob dies möglich ist. Leider ist es fünf Jahre alt, hat sehr wenig Beachtung gefunden und es gibt keine andere Lösung als den Rückgriff auf Schlösser (was seinen Zweck zunichte macht). Möglicherweise hat sich seitdem ein besserer Weg ergeben.
(Beispiel zur Verdeutlichung bearbeitet)