gpt4 book ai didi

java - 带 ReentrantLocks 的资源管理器

转载 作者:塔克拉玛干 更新时间:2023-11-02 19:29:32 26 4
gpt4 key购买 nike

我正在尝试实现一个资源处理程序类,它将资源(字符串,存储在数组中)分配给多个客户端,这些客户端可以尝试获取一组资源的锁并通过锁方法给出的 ID 解锁它们.

我正在尝试使用公平的 ReentrantReadWriteLock-s,每个资源一个。

我只看到客户端的日志。

有几个问题,有的时候线程不会停止请求和获取资源,有的时候死锁,有的时候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);
}
}

最佳答案

您的程序中有几个问题是导致锁定和错误的原因:

  • 一般来说:将全局变量声明为final。你不想不小心弄乱他们。此外,这还允许您将它们用作同步对象。

  • long 不保证是原子的,运算符++ 也不保证。 32 位 JVM 必须分两步编写此代码,因此 - 理论上 - 会导致系统出现重大故障。最好使用 AtomicLong。

  • getLock 不是线程安全的。示例:

线程 A 为资源 1、3、5 调用 getLock
线程B同时为资源2,5,3调用getLock
线程 A 在 1、3 上被授予锁,然后暂停
线程 B 在 2、5 上被授予锁定,然后暂停
线程 A 现在等待线程 B 的 5,线程 B 现在等待线程 A 的 3。
死锁。

请注意,释放方法不需要同步,因为它无法锁定任何其他线程。

  • ++lockNum 如果同时调用,将导致两个线程弄乱它们的锁定值,因为这是一个全局变量。

这是工作状态下的代码:

  private static final AtomicLong lockNum = new AtomicLong(0);
private static final ConcurrentHashMap<Long, Set<String>> usedResources = new ConcurrentHashMap<Long, Set<String>>();
private static final ConcurrentHashMap<String, ReentrantReadWriteLock> resources = new ConcurrentHashMap<String, ReentrantReadWriteLock>();

static {
for (int i = 0; i < SharedValues.RESOURCE_LIST.length; ++i) {
String res = SharedValues.RESOURCE_LIST[i];
ReentrantReadWriteLock lc = new ReentrantReadWriteLock(true);
resources.put(res, lc);
}
}

public static long getLock(Set<String> mNeededRes, boolean mMethod) {
synchronized (resources) {
if (mMethod == SharedValues.READ_METHOD) {
for (String mn : mNeededRes) {
resources.get(mn).readLock().lock();
}
} else {
for (String mn : mNeededRes) {
resources.get(mn).writeLock().lock();
}
}
}
final long lockNumber = lockNum.getAndIncrement();
usedResources.put(lockNumber, mNeededRes);
return lockNumber;
}

public static void releaseLock(final long mLockID) {
if (!usedResources.containsKey(mLockID)) {
System.out.println("returned, no such key as: " + mLockID);
return;
}

final Set<String> toBeReleased = usedResources.remove(mLockID);

for (String s : toBeReleased) {
final ReentrantReadWriteLock lock = resources.get(s);
if (lock.isWriteLockedByCurrentThread()) {
lock.writeLock().unlock();
} else {
lock.readLock().unlock();
}
}
}

关于java - 带 ReentrantLocks 的资源管理器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16253593/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com