Предположим, есть карта:
// key->number of resources occupied
Map map = new ConcurrentHashMap();
- Несколько задач выполняются в разных потоках.
- Каждая задача перед выполнением проверяет, доступны ли ресурсы. Если нет, он ждет, пока их освободит другая задача, в противном случае обновляет счетчик, тем самым временно забирая необходимые ресурсы себе. Этот фрагмент кода должен выполняться атомарно.
- После необходимых вычислений задача «освобождает» ресурсы и уменьшает счетчик.
// must be atomic
if (map.get(key) + count > 25) {
sleep(100);
} else {
map.put(key, map.get(key) + count);
}
// do some computations
// atomic analog of map.put(key, map.get(key) - count);
map.merge(key, count, (current, next) -> current - next);
}
Я экспериментировал с методами ConcurrentHashMap, в частности пытался заснуть в методе слияния, но код зависает в момент выполнения финальной строки кода map.merge (ключ, счетчик, (текущий, следующий) -> текущий - следующий).
Пример кода:
map.merge(key, count, (current, next) -> {
while (current + next > 25) {
sleep(100);
current = map.get(key);
}
return current + next;
}
);
EDIT1
Я попробовал класс Semaphore. Прокомментируйте, правильно ли я его использую?
Map map = new ConcurrentHashMap();
private void do(long key, int count) {
Semaphore semaphore = map.computeIfAbsent(key, s -> new Semaphore(5));
semaphore.acquire(count);
// do some computations
semaphore.release(count);
}
Подробнее здесь: https://stackoverflow.com/questions/793 ... atomically
Мобильная версия