Java ReentrantLock.unlock/await()/signal()未引发IllegalMonitorStateException

Java ReentrantLock.unlock/await()/signal()未引发IllegalMonitorStateException,java,multithreading,locking,Java,Multithreading,Locking,我哪里做错了?即使我的使用者线程没有持有锁,程序也不会对任何锁调用(unlock/await/signal)抛出非法监视器状态异常 更新: private final ReentrantLock lock = new ReentrantLock(); private final Condition producers = lock.newCondition(); private final Condition consumers = lock.newCondition(); @Override

我哪里做错了?即使我的使用者线程没有持有锁,程序也不会对任何锁调用(unlock/await/signal)抛出非法监视器状态异常

更新:

private final ReentrantLock lock = new ReentrantLock();
private final Condition producers = lock.newCondition();
private final Condition consumers = lock.newCondition();

@Override
public void run() {

    while (true) {
        try {
            //lock.lockInterruptibly();
            try {
                while (sharedResource.isEmpty()) {
                    printErr(name + " : Queue Empty ..");
                    consumers.await(500, TimeUnit.MILLISECONDS);
                }

                String obj = sharedResource.remove(0);
                printOut(name + " : " + obj);
                if (obj.equals(POISON_PILL)) {
                    sharedResource.add(POISON_PILL);
                    // System.err.println(name +" Taking break");
                    break;
                }

                producers.signal();
            } finally {
                lock.unlock();
            }
            Thread.sleep(100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        // if(debug)System.err.println("Consumer Looping");
    }
}
void java.util.concurrent.locks.ReentrantLock.unlock()

根据Java。 公开作废解锁() 试图释放此锁。
如果当前线程是此锁的保持器,则保持计数将减少。如果保持计数现在为零,则释放锁
如果当前线程不是此锁的持有者,则会抛出IllegalMonitorStateException

此问题似乎基于一些不正确的假设/陈述

  • Java
    ReentrantLock
    类没有
    await
    signal
    方法

  • 这意味着
    消费者
    很可能不是
    可重入锁
    。。。代码段中没有任何内容调用
    signal
    (或
    singnal
    (sic))

  • 根据javadoc的说法,
    ReentrantLock
    lock和unlock方法不会抛出
    IllegalMonitorStateException
    。我也不希望他们这样做,因为lock和unlock方法并没有像原始监视器/互斥体那样工作

  • 好的,从
    对象中获取该异常的唯一方法是使用基本互斥操作
    等待
    通知
    。。。这似乎是对
    Lock
    对象的不当使用。(如果要使用这些操作,任何对象都可以,包括一个普通的
    对象
    实例。)

    Lock
    类被设计为提供与Java基本锁正交的锁,并且不受严格块结构的限制。它们不直接提供等待和信号。如果需要,您需要创建一个
    条件
    ;e、 g.使用
    Lock.newCondition()
    。请注意,如果当前线程未持有
    ,Condition.await和signal方法通常会抛出
    IllegalMonitorStateException
    。。。但这种行为是具体实施的;看


    因此,假设
    消费者
    是一个
    条件
    ,那么它可能不会引发异常的原因有两个:

  • 这可能不是由
    Lock
    表示的
    Lock
    的条件

  • 实际的
    类可以提供不需要持有锁的
    条件
    对象

  • 不幸的是,您的代码片段缺少一些能够解决这些问题的重要线索


    更新

    我将您的代码转换为可以运行的代码:

    package test;
    
    import java.util.concurrent.TimeUnit;
    import java.util.concurrent.locks.Condition;
    import java.util.concurrent.locks.ReentrantLock;
    
    public class Lochy {
    
        public static void main(String[] args) {
            ReentrantLock lock = new ReentrantLock();
            Condition producers = lock.newCondition();
            Condition consumers = lock.newCondition();
    
            while (true) {
                try {
                    try {
                        for (int i = 0; i < 3; i++) {
                            System.out.println("wait " + i);
                            consumers.await(500, TimeUnit.MILLISECONDS);
                        }
                        producers.signal();
                    } finally {
                        lock.unlock();
                    }
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    
    封装测试;
    导入java.util.concurrent.TimeUnit;
    导入java.util.concurrent.locks.Condition;
    导入java.util.concurrent.locks.ReentrantLock;
    公共级洛希{
    公共静态void main(字符串[]args){
    ReentrantLock=新的ReentrantLock();
    条件生产者=lock.newCondition();
    条件使用者=lock.newCondition();
    while(true){
    试一试{
    试一试{
    对于(int i=0;i<3;i++){
    System.out.println(“等待”+i);
    消费者。等待(500,时间单位。毫秒);
    }
    生产者。信号();
    }最后{
    lock.unlock();
    }
    睡眠(100);
    }捕捉(中断异常e){
    e、 printStackTrace();
    }
    }
    }
    }
    
    当我运行它时,我在
    解锁
    处看到一个
    非法监视器状态异常

    当我注释掉
    unlock()
    时,我在
    wait
    中看到
    IllegalMonitorStateException

    事后看来,很清楚发生了什么。在这两种情况下,
    await
    都会引发
    IllegalMonitorStateException
    ,但当您在
    finally
    块中调用
    unlock()
    时,会引发另一个
    IllegalMonitorStateException
    。。。所以你看不到第一个


    简而言之,这些方法的行为完全符合规范的要求。

    这看起来像Java代码。为什么你也用c#标记它?为什么他们会抛出异常?更新了我的帖子。消费者和生产者是条件。根据java文档,如果当前线程没有持有锁,则调用unlock with throw IllegalMonitorStateException。