在多线程中锁定和解锁 java

lock and unlock in multi thread java

我在我的代码中使用锁定和解锁并启动一些客户和生产者线程。 第 lock.waite 行抛出 IllegalMonitorStateException.Why? 有了锁,在一个Thread中不提供使用这个列表的条件?

 static class Customeer extends Thread {
            private List<String> list;
            private Lock lock;
            public Customeer(List<String> list, Lock lock) {
                this.list = list;
                this.lock = lock;
            }
            @Override
            public void run() {   
                lock.lock();
                if (list.size() == 0) {
                    try {
                        list.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                    list.remove(0);
                    lock.unlock();
            }
        }
    
        static class Producer extends Thread {
            private List<String> list;
            private Lock lock;
            public Producer(List<String> list, Lock lock) {
                this.list = list;
                this.lock = lock;
            }
            @Override
            public void run() {
                    lock.lock();
                    list.add("hello");
                    list.notify();
                    lock.unlock();
            }
        }

您的代码存在一些问题,即:

  1. list.wait();除非在同步方法(或块代码)中,否则无法获取列表的监视器。

  2. list.notify();,除非在同步方法(r 块代码)中,否则无法释放列表的监视器。

您不能使用 none 同步方法或部分中的 .wait().notify()

像该片段一样更改您的代码:

 static class Customeer extends Thread {
            private List<String> list;
            private Lock lock;
            public Customeer(List<String> list, Lock lock) {
                this.list = list;
                this.lock = lock;
            }
            @Override
            public void run() {   
                lock.lock();
                if (list.size() != 0) {
                   list.remove(0);
                }                      
                lock.unlock();
            }
        }
    
        static class Producer extends Thread {
            private List<String> list;
            private Lock lock;
            public Producer(List<String> list, Lock lock) {
                this.list = list;
                this.lock = lock;
            }
            @Override
            public void run() {
                    lock.lock();
                    list.add("hello");                    
                    lock.unlock();
            }
        }

这些字符串正在调用 IllegalMonitorStateException

line lock.wait throws IllegalMonitorStateException. Why?

其实并没有这条线

然而,有一行调用list.wait() 是你的问题的原因。

为了在对象上调用 wait(),您必须首先持有该对象的原始互斥锁。您只能使用 synchronized 获得 那种 类型的锁。 (synchronized 方法或 synchronized 块。)

你的情况:

  • 您正在 List 实例上调用 wait
  • 您正在锁定 Lock 个实例。
  • 您为 Object.wait 持有错误的锁。您持有的是 Lock 锁,而不是原始互斥锁。

所以...如果您想在 Lock 实例上执行相当于等待和通知的操作,那么您需要做的就是调用 Lock.newCondition() 来获取 Condition 目的。然后你像这样使用它:

private final Lock lock = ...
private final Condition cond = lock.newCondition();

try {
    lock.acquire();
    while (!the_condition_we_are_waiting_for) {
        cond.await();
    }
    // do stuff
} finally {
   lock.release();
}

作为参考,如果您重写上面的代码以使用原始互斥体,它看起来会像这样。

private final Object lock = new Object();

synchronized(lock) {
    while (!the_condition_we_are_waiting_for) {
        lock.wait();
    }
    // do stuff
}

(您可以使用 any 对象作为锁,但最好使用隐藏的对象,并且不会被任何其他代码锁定。 )


总而言之,要么使用带有 synchronizedObject.waitObject.notify* 的原始互斥锁,要么使用带有 Lock.acquire、[=32= 的 Lock ]、Condition.awaitCondition.signal。不要试图混合使用这两种锁定和条件变量。