В Java ConcurrentMap
есть remove(key, expectedValue)
, это возвращает одно из:
- Ожидаемое значение было там и было удалено.
- Ожидаемого значения не было, поэтому оно не было удалено.
Но я хочу получить одно из:
- Ожидаемое значение было там и было удалено.
- Под этим ключом есть значение, но не ожидаемое, поэтому оно не было удалено.
- Под этим ключом нет значения, поэтому он не был удален.
Как я могу получить эту информацию одновременно и потокобезопасным способом?
Это код, который я пытаюсь обезопасить
// attempt to remove the old session...
if (!sessions.remove(player.getId(), existing)) {
// it was not removed...
if (sessions.containsKey(player.getId())) { // TODO threadsafe
// ...because in the meantime some other thread logged in as that user
throw new ServiceError(LobbyService.ERR_LOGIN_INVALID, Maps.create("reason", "already-logged-in"));
} else {
// ...because it was no longer there, which is as it should be
}
} else {
// it was removed, which is bad, because it shouldn't have been there still
log.warn("Kicking old session of " + player.getId() + " failed");
}
или обобщенно:
if (!sessions.remove(key, expected)) {
if (sessions.containsKey(key)) { // TODO threadsafe
// 2
} else {
// 3
}
} else {
// 1
}