Wait()返回后,Java条件无法重新获取与其关联的锁(ReentrantLock) import java.util.LinkedList; 导入java.util.concurrent.locks.Condition; 导入java.util.concurrent.locks.ReentrantLock; 福班{ 私有可重入锁; 私人条件; 私有线程; 私有链接列表(msgQueue); 公共食物({ _锁=新的可重入锁(); _cond=_lock.newCondition(); _msgQueue=newlinkedlist(); startThread(); } public void putMsg(字符串msg)引发异常{ _lock.lock(); _msgQueue.addLast(msg); _条件信号(); System.out.println(Thread.currentThread().getId()+“:信号写入线程”); _lock.unlock(); System.out.println(Thread.currentThread().getId()+“:Unlocked”); } 私有void startThread(){ _thr=新线程(){ 公开募捐{ _lock.lock(); while(true){ 试一试{ 而(!\msgQueue.isEmpty()){ 字符串msg=_msgQueue.getFirst(); System.out.println(msg); _msgQueue.removeFirst(); } System.out.println(Thread.currentThread().getId()+“:getHoldCount:”+_lock.getHoldCount()); System.out.println((Thread.currentThread().getId()+”:isLocked:“+_lock.isLocked()); System.out.println(Thread.currentThread().getId()+”:isHeldByCurrentThread:“+_lock.isHeldByCurrentThread()); System.out.println(Thread.currentThread().getId()+“:waiting…”); _条件等待(); System.out.println(Thread.currentThread().getId()+“:Write Thread aware”); }捕获(例外e){ e、 printStackTrace(); 打破 }最后{ 试一试{ _lock.unlock(); }捕获(例外e){ } } } System.out.println(“写入线程退出”); } }; _thr.start(); } } 公共类锁测试{ 公共静态void main(字符串[]args)引发异常{ Foo-Foo=新的Foo(); foo.putMsg(“味精1”); foo.putMsg(“味精2”); 睡眠(1000); foo.putMsg(“味精3”); } } 运行一次后的代码输出: 1:信号写入线程。 1:解锁。 1:信号写入线程。 1:解锁。 味精1 味精2 8:getHoldCount:1 8:isLocked:true 8:isHeldByCurrentThread:真 8:等待。。。 1:信号写入线程。 1:解锁。 8:写入线程唤醒 味精3 8:getHoldCount:0 8:已锁定:false 8:isHeldByCurrentThread:false 8:等待。。。 写入线程退出。 java.lang.IllegalMonitorStateException位于 位于的java.util.concurrent.locks.ReentrantLock$Sync.tryRelease(未知源) java.util.concurrent.locks.AbstractQueuedSynchronizer.release(未知源)位于 位于的java.util.concurrent.locks.AbstractQueuedSynchronizer.fullyRelease(未知源) java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(未知源) 在Foo$1.run(LockTest.java:44)

Wait()返回后,Java条件无法重新获取与其关联的锁(ReentrantLock) import java.util.LinkedList; 导入java.util.concurrent.locks.Condition; 导入java.util.concurrent.locks.ReentrantLock; 福班{ 私有可重入锁; 私人条件; 私有线程; 私有链接列表(msgQueue); 公共食物({ _锁=新的可重入锁(); _cond=_lock.newCondition(); _msgQueue=newlinkedlist(); startThread(); } public void putMsg(字符串msg)引发异常{ _lock.lock(); _msgQueue.addLast(msg); _条件信号(); System.out.println(Thread.currentThread().getId()+“:信号写入线程”); _lock.unlock(); System.out.println(Thread.currentThread().getId()+“:Unlocked”); } 私有void startThread(){ _thr=新线程(){ 公开募捐{ _lock.lock(); while(true){ 试一试{ 而(!\msgQueue.isEmpty()){ 字符串msg=_msgQueue.getFirst(); System.out.println(msg); _msgQueue.removeFirst(); } System.out.println(Thread.currentThread().getId()+“:getHoldCount:”+_lock.getHoldCount()); System.out.println((Thread.currentThread().getId()+”:isLocked:“+_lock.isLocked()); System.out.println(Thread.currentThread().getId()+”:isHeldByCurrentThread:“+_lock.isHeldByCurrentThread()); System.out.println(Thread.currentThread().getId()+“:waiting…”); _条件等待(); System.out.println(Thread.currentThread().getId()+“:Write Thread aware”); }捕获(例外e){ e、 printStackTrace(); 打破 }最后{ 试一试{ _lock.unlock(); }捕获(例外e){ } } } System.out.println(“写入线程退出”); } }; _thr.start(); } } 公共类锁测试{ 公共静态void main(字符串[]args)引发异常{ Foo-Foo=新的Foo(); foo.putMsg(“味精1”); foo.putMsg(“味精2”); 睡眠(1000); foo.putMsg(“味精3”); } } 运行一次后的代码输出: 1:信号写入线程。 1:解锁。 1:信号写入线程。 1:解锁。 味精1 味精2 8:getHoldCount:1 8:isLocked:true 8:isHeldByCurrentThread:真 8:等待。。。 1:信号写入线程。 1:解锁。 8:写入线程唤醒 味精3 8:getHoldCount:0 8:已锁定:false 8:isHeldByCurrentThread:false 8:等待。。。 写入线程退出。 java.lang.IllegalMonitorStateException位于 位于的java.util.concurrent.locks.ReentrantLock$Sync.tryRelease(未知源) java.util.concurrent.locks.AbstractQueuedSynchronizer.release(未知源)位于 位于的java.util.concurrent.locks.AbstractQueuedSynchronizer.fullyRelease(未知源) java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(未知源) 在Foo$1.run(LockTest.java:44),java,locking,conditional-statements,Java,Locking,Conditional Statements,问题是: 根据,当线程返回时,保证持有该锁。但是从输出中,我们可以看到,在await()返回后,它不会重新获得锁。这是一个错误还是我犯了一些错误 根据,当线程返回时,保证持有该锁 是的,但它还表示线程在调用方法之前必须持有锁: 调用此方法时,假定当前线程持有与此条件关联的锁。由实施部门确定是否存在这种情况,如果不是,如何应对。通常,将引发异常(例如IllegalMonitorStateException),实现必须记录该事实 这与“普通”监视器(对象#等待)的工作方式相同:开始等待时必须持有锁(

问题是: 根据,当线程返回时,保证持有该锁。但是从输出中,我们可以看到,在await()返回后,它不会重新获得锁。这是一个错误还是我犯了一些错误

根据,当线程返回时,保证持有该锁

是的,但它还表示线程在调用方法之前必须持有锁:

调用此方法时,假定当前线程持有与此条件关联的锁。由实施部门确定是否存在这种情况,如果不是,如何应对。通常,将引发异常(例如IllegalMonitorStateException),实现必须记录该事实


这与“普通”监视器(对象#等待)的工作方式相同:开始等待时必须持有锁(对象#等待时使用同步块,此处使用锁#锁)。锁将被释放,您等待。等待结束后,您也会再次持有锁。

您可以显示一些代码吗?我正在尝试发布我的代码,编辑器标记代码检查总是拒绝我的发布…最后,代码来了…是的,我在wait()之前持有锁,您可以看到run()方法中的第一条语句_lock.lock()。我将lock()放入while(true)中,代码可以正确运行,但我必须这样做吗?每次等待()返回后都需要锁定()吗?每次要等待()时都需要锁定()。您可能只需将lock()保持在顶部,但现在,每次迭代都有一个finally unlock()。
import java.util.LinkedList;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

class Foo {
    private ReentrantLock _lock;
    private Condition _cond;
    private Thread _thr;
    private LinkedList<String> _msgQueue;

    public Foo() {
        _lock = new ReentrantLock();
        _cond = _lock.newCondition();
        _msgQueue = new LinkedList<String>();
        startThread();
    }

    public void putMsg(String msg) throws Exception {
        _lock.lock();
        _msgQueue.addLast(msg);
        _cond.signal();
        System.out.println(Thread.currentThread().getId() + ": Signal write thread.");
        _lock.unlock();
        System.out.println(Thread.currentThread().getId() + ": Unlocked.");
    }

    private void startThread() {
        _thr = new Thread() {
            public void run() {
                _lock.lock();
                while(true) {
                    try {
                        while (!_msgQueue.isEmpty()) {
                            String msg = _msgQueue.getFirst();
                            System.out.println(msg);
                            _msgQueue.removeFirst();
                        }

                        System.out.println(Thread.currentThread().getId() + ": getHoldCount:" + _lock.getHoldCount());
                        System.out.println((Thread.currentThread().getId() + ": isLocked:" + _lock.isLocked()));
                        System.out.println(Thread.currentThread().getId() + ": isHeldByCurrentThread:" + _lock.isHeldByCurrentThread());
                        System.out.println(Thread.currentThread().getId() + ": Awaiting...");

                        _cond.await();

                        System.out.println(Thread.currentThread().getId() + ": Write thread awaken");

                    } catch (Exception e) {
                        e.printStackTrace();
                        break;
                    } finally {
                        try {
                            _lock.unlock();
                        } catch (Exception e) {
                        }
                    }
                }
                System.out.println("Write thread exit.");
            }
        };

        _thr.start();
    }
}

public class LockTest {
    public static void main(String[] args) throws Exception {
        Foo foo = new Foo();
        foo.putMsg("Msg 1");
        foo.putMsg("Msg 2");
        Thread.sleep(1000);
        foo.putMsg("Msg 3");
    }
}
The code output after one running: 1: Signal write thread. 1: Unlocked. 1: Signal write thread. 1: Unlocked. Msg 1 Msg 2 8: getHoldCount:1 8: isLocked:true 8: isHeldByCurrentThread:true 8: Awaiting... 1: Signal write thread. 1: Unlocked. 8: Write thread awaken Msg 3 8: getHoldCount:0 8: isLocked:false 8: isHeldByCurrentThread:false 8: Awaiting... Write thread exit. java.lang.IllegalMonitorStateException at java.util.concurrent.locks.ReentrantLock$Sync.tryRelease(Unknown Source) at java.util.concurrent.locks.AbstractQueuedSynchronizer.release(Unknown Source) at java.util.concurrent.locks.AbstractQueuedSynchronizer.fullyRelease(Unknown Source) at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(Unknown Source) at Foo$1.run(LockTest.java:44)