Атомарная операция ConcurrentHashMap для удаления всех записей, кроме одной - PullRequest
0 голосов
/ 10 ноября 2018

Учитывая ConcurrentHashMap<String, String> содержит следующие записи:

this.map = new ConcurrentHashMap<>();
this.map.put("user", "user description");
this.map.put("session", "session description");
this.map.put("test", "test description");

Доступ к карте осуществляется несколькими потоками.

Как удалить все ключи, кроме session атомарным способом?

Будет ли этот код работать, как я ожидаю, без условий гонки? Является ли forEach метод атомарным? Есть ли другой способ добиться этого атомарно?

map.forEach((key, value) -> {
    if (!key.equals("session")) {
        map.remove(key);
    }
});

1 Ответ

0 голосов
/ 10 ноября 2018

Ваш forEach() не будет происходить атомарно, поскольку каждый вызов remove() синхронизируется независимо.

Вы можете попробовать сделать это, создав новую карту и заменив ее старой:

ConcurrentMap<String, String> newMap = new ConcurrentHashMap<>();
newMap.put("session", this.map.get("session"));
this.map = newMap;

Просмотр потоков this.map до того, как коммутатор будет иметь старый вид, но атомарное «удаление» можно считать происходящим при назначении новой карты. Единственная другая проблема заключается в том, что другой поток изменяет значение, связанное с "session" в исходной карте между 2-й и 3-й строками (или если этот ключ даже не присутствует), но, как вы сказали в ваш комментарий этого никогда не происходит.

...