gpt4 book ai didi

java - 将ReentrantLock放入HashMap时锁丢失

转载 作者:行者123 更新时间:2023-11-30 11:23:58 27 4
gpt4 key购买 nike

我试图让多个消费者线程监听一个生产者线程,直到生产者有东西要发布。我认为可以工作的代码“失去”了放入和取出共享类的锁定。

在 Controller 类中,我启动线程运行 服务器server = new Server();

    Thread serverThread = new Thread(server,"Server");
serverThread.start();

Consumer consumer = new Consumer();
Thread consumerThread;
for (int i =0;i<6;i++){
consumerThread = new Thread(consumer,"Consumer No:"+i);
consumerThread.start();
server.threadRefs[i]= consumerThread;
}

消费者类将线程的详细信息放入Map如下:

public class Consumer implements Runnable {

private ReentrantLock lock = new ReentrantLock();
private Condition cond = lock.newCondition();

@Override
public void run() {

long threadID = Thread.currentThread().getId();
while (true) {
try {

lock.lock();

MDRequest.threadLocks.put(threadID, lock);
System.out.println("Thread " + threadID + " lock = " + lock.toString());

cond.await();
System.out.println("Thread " + threadID + " done waiting");
} catch (InterruptedException ex) {
System.out.println("Interruped " + threadID);
} finally {
lock.unlock();
}

System.out.println("Finished " + threadID);
}

}

共享类很简单:

public class MDRequest {

protected static ConcurrentHashMap<Long, ReentrantLock> threadLocks = new ConcurrentHashMap<Long, ReentrantLock>();

服务器有以下 run() 方法:

public void run() {
try {
Thread.sleep(5000);
} catch (InterruptedException ex) {
Logger.getLogger(Server.class.getName()).log(Level.SEVERE, null, ex);
}
Set<Long> keys = MDRequest.threadLocks.keySet();
Long[] threadIDs = keys.toArray(new Long[1]);

// generates a random series of numbers for each thread and notifies threads about them
while (true) {


Random random = new Random();
int threadRef = random.nextInt(5);

System.out.println("About to signal thread " + threadIDs[threadRef].toString());

// notify the thread of the data
ReentrantLock lock = MDRequest.threadLocks.get(threadIDs[threadRef]);
System.out.println("Thread " + threadIDs[threadRef].toString() + " lock = " + lock.toString());

Condition cond = lock.newCondition();
cond.signal();
lock.unlock();

}

输出如下:

Thread 11  lock = java.util.concurrent.locks.ReentrantLock@272d7a10[Locked by thread Consumer No:0]
Thread 12 lock = java.util.concurrent.locks.ReentrantLock@272d7a10[Locked by thread Consumer No:1]
Thread 13 lock = java.util.concurrent.locks.ReentrantLock@272d7a10[Locked by thread Consumer No:2]
Thread 14 lock = java.util.concurrent.locks.ReentrantLock@272d7a10[Locked by thread Consumer No:3]
Thread 15 lock = java.util.concurrent.locks.ReentrantLock@272d7a10[Locked by thread Consumer No:4]
Thread 16 lock = java.util.concurrent.locks.ReentrantLock@272d7a10[Locked by thread Consumer No:5]
About to signal thread 14
Thread 14 lock = java.util.concurrent.locks.ReentrantLock@272d7a10[Unlocked]
Exception in thread "Price Server" java.lang.IllegalMonitorStateException
at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.signal(AbstractQueuedSynchronizer.java:1885)
at faster.Server.run(Server.java:46)
at java.lang.Thread.run(Thread.java:695)

从服务器类的输出中我可以看到,当我从 map 中读取锁时,它现在的状态为“未锁定”。当它被放入时,它在线程 14 上的状态为锁定。

为什么对 ReentrantLock 的引用会“丢失”锁?

有没有办法在多个消费者线程和服务器线程之间以锁不丢失的方式共享锁?

最佳答案

您遇到的问题可能是因为服务器中的以下行

Condition cond = lock.newCondition();
cond.signal();
lock.unlock();

您是否需要从Server 调用unlock() 以获得被Consumer 锁定的Lock >?我认为调用 signal() 就足够了。

想想这个。

关于java - 将ReentrantLock放入HashMap时锁丢失,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20894516/

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