首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >当将ReentrantLock放入HashMap时,锁丢失

当将ReentrantLock放入HashMap时,锁丢失
EN

Stack Overflow用户
提问于 2014-01-03 00:34:57
回答 2查看 1.1K关注 0票数 2

我正在尝试使多个使用者线程侦听一个生产者线程,直到生产者有要发布的东西。我认为可以工作的代码“丢失”了被放入共享类和从共享类中取出的锁。

在控制器类中,我使用Server = new ()启动运行的线程;

代码语言:javascript
复制
    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中,如下所示:

代码语言:javascript
复制
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);
    }

}

共享类只是:

代码语言:javascript
复制
public class MDRequest {

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

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

代码语言:javascript
复制
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();

    }

产出如下:

代码语言:javascript
复制
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)

从Server类的输出中,我可以看到,当我从Map中读取锁时,它现在的状态是"Unlocked“。当它被放进去时,它的状态是锁在14线程上。

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

是否有一种在多个使用者线程和服务器线程之间以不丢失锁的方式共享锁的方法?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2014-01-03 02:48:47

问题是Server类中的线程试图解锁,但没有锁定Lock

代码语言:javascript
复制
lock.unlock();

请参阅 documentation,此处有明确说明:

如果当前线程不是此锁的持有者,则抛出IllegalMonitorStateException

票数 0
EN

Stack Overflow用户

发布于 2014-01-03 02:11:52

您所面临的问题可能是因为服务器中的下面一行

代码语言:javascript
复制
Condition cond = lock.newCondition();
cond.signal();
lock.unlock();

您是否需要从unlock()调用Server中的Lock,以获得被Consumer锁定的Lock?我想打电话给signal()就足够了。

想想看。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/20894516

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档