Вы не можете гарантировать, что не будет тупиков, если у вас нет эксклюзивного контроля над вашими замками. Интернированные String
видны во всем мире, поэтому они плохой кандидат.
Вместо этого используйте карту между ключами и соответствующими им замками. Вы можете использовать синхронизированный доступ к параллельной карте или использовать ConcurrentMap
. Я не уверен, что дешевле, но я бы склонялся к ConcurrentMap
, потому что это выражает ваше намерение кратко.
ReadWriteLock trial = new ReentrantReadWriteLock(fair);
ReadWriteLock lock = locks.putIfAbsent(key, trial);
if (lock == null) {
/* The current thread won the race to create lock for key. */
lock = trial;
}
(Использование ReadWriteLock
необязательно; с его помощью вы можете сделать что-то необычное, например, разрешить одновременное чтение кэшированного значения несколькими потоками, но при этом другой поток может получить эксклюзивную блокировку, когда значение необходимо обновить.)
Может быть дорого создавать много блокировок, которые в конечном итоге будут отброшены, поскольку блокировка уже существует. Или вы можете использовать старую среду выполнения без java.util.concurrent
. В таких случаях вы можете синхронизировать данные на карте:
Object lock;
synchronized (locks) {
if (locks.containsKey(key))
lock = locks.get(key);
else {
lock = new Object();
locks.put(key, object);
}
}