Я пытаюсь реализовать класс обработчика ресурсов, который назначает ресурсы (строки, хранящиеся в массиве) нескольким клиентам, которые могут попытаться получить блокировку набора ресурсов и разблокировать их с помощью идентификатора, заданного методом блокировки.
Я пытаюсь использовать справедливые ReentrantReadWriteLock-ы, по одному для каждого ресурса.
Я вижу только журнал клиента.
Есть несколько проблем: иногда поток не прекращает запрашивать и получать ресурсы, иногда возникает взаимоблокировка, а иногда не удается выполнить releaseLock. Любые советы приветствуются.
public class ResHandler {
//ID-s of the granted resource lists
private static long lockNum = 0;
//Resources are identified by strings, each client has a list of demanded resources
//we store these when granted, along with an ID
private static ConcurrentHashMap<Long, Set<String>> usedResources
= new ConcurrentHashMap<Long, Set<String>>();
//We store a lock for each resource
private static ConcurrentHashMap<String, ReentrantReadWriteLock> resources
= new ConcurrentHashMap<String, ReentrantReadWriteLock>();
//Filling our resources map with the resources and their locks
static {
for (int i = 0; i < SharedValues.RESOURCE_LIST.length; ++i) {
String res = SharedValues.RESOURCE_LIST[i];
//Fair reentrant lock
ReentrantReadWriteLock lc = new ReentrantReadWriteLock(true);
resources.put(res, lc);
}
}
//We get a set of the required resources and the type of lock we have to use
public static long getLock(Set<String> mNeededRes, boolean mMethod) {
//!!!
if (mMethod == SharedValues.READ_METHOD) {
//We try to get the required resources
for (String mn : mNeededRes)
resources.get(mn).readLock().lock();
//After grandted, we put them in the usedResources map
++lockNum;
usedResources.put(lockNum, mNeededRes);
return lockNum;
}
//Same thing, but with write locks
else {
for (String mn : mNeededRes)
resources.get(mn).writeLock().lock();
++lockNum;
usedResources.put(lockNum, mNeededRes);
return lockNum;
}
}
//Releasing a set of locks by the set's ID
public static void releaseLock(long mLockID) {
if (!usedResources.containsKey(mLockID)) {
System.out.println("returned, no such key as: " + mLockID);
return;
}
Set<String> toBeReleased = usedResources.get(mLockID);
//Unlocking every lock from this set
for (String s : toBeReleased) {
if (resources.get(s).isWriteLockedByCurrentThread())
resources.get(s).writeLock().unlock();
else
resources.get(s).readLock().unlock();
}
//Deleting from the map
usedResources.remove(mLockID);
}
}
lockNum
: вы увеличиваете его, второй поток увеличивает его, и оба затем используют одно и то же значение.volatile
здесь не помогает, возможно, синхронизация функции поможет. Кстати: использование единой блокировки для всего управления ресурсами решит вашу проблему, хотя вам придется реализовать несколько функций мелкозернистой блокировки самостоятельно. - person Ulrich Eckhardt   schedule 27.04.2013