[英]Lock is lost when putting ReentrantLock into HashMap
我试图使多个消费者线程侦听一个生产者线程,直到生产者发布一些东西。 我认为可以工作的代码“失去了”进入共享类和从共享类中取出的锁。
在控制器类中,我启动运行Server 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)
从服务器类的输出int中,我可以看到,当我从Map中读取锁定时,它现在的状态为“未锁定”。 放入线程14时,其状态为“已锁定”。
为什么对ReentrantLock的引用会“丢失”该锁?
有没有一种方法可以在多个使用者线程和服务器线程之间共享锁,而不会丢失锁?
您面临的问题可能是由于服务器中的以下行
Condition cond = lock.newCondition();
cond.signal();
lock.unlock();
你需要调用unlock()
从Server
的Lock
,其被锁定的Consumer
? 我认为调用signal()
就足够了。
考虑一下。
问题是Server
类中的线程尝试解锁但尚未锁定Lock
lock.unlock();
请参阅ReentrantLock
文档 ,其中有明确说明:
如果当前线程不是此锁的持有者,则抛出
IllegalMonitorStateException
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.