多线程java中的锁定和解锁

多线程java中的锁定和解锁,java,multithreading,locking,Java,Multithreading,Locking,我在我的代码中使用lock和unlock,并启动一些客户和生产商线程。 line lock.waite抛出非法监视器状态异常。为什么? 有了锁,在一个线程中不提供使用此列表的条件 static class Customeer extends Thread { private List<String> list; private Lock lock; public Customeer(List<String

我在我的代码中使用lock和unlock,并启动一些客户和生产商线程。 line lock.waite抛出非法监视器状态异常。为什么? 有了锁,在一个线程中不提供使用此列表的条件

 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();
            }
        }
静态类Customeer扩展线程{
私人名单;
私家锁;
公共客户(列表、锁定){
this.list=列表;
this.lock=锁;
}
@凌驾
public void run(){
lock.lock();
if(list.size()==0){
试一试{
list.wait();
}捕捉(中断异常e){
e、 printStackTrace();
}
}
列表。删除(0);
lock.unlock();
}
}
静态类生成器扩展线程{
私人名单;
私家锁;
公共制作人(列表、锁定){
this.list=列表;
this.lock=锁;
}
@凌驾
公开募捐{
lock.lock();
添加(“你好”);
list.notify();
lock.unlock();
}
}

您的代码有一些问题,即:

  • list.wait()除非处于同步方法(或块代码)内,否则无法获取列表的监视器

  • list.notify(),除非处于同步方法(r块代码)内,否则无法释放列表的监视器

  • 您不能从none synchronized方法或节中使用
    .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();
                }
            }
    
    静态类Customeer扩展线程{
    私人名单;
    私家锁;
    公共客户(列表、锁定){
    this.list=列表;
    this.lock=锁;
    }
    @凌驾
    public void run(){
    lock.lock();
    如果(list.size()!=0){
    列表。删除(0);
    }                      
    lock.unlock();
    }
    }
    静态类生成器扩展线程{
    私人名单;
    私家锁;
    公共制作人(列表、锁定){
    this.list=列表;
    this.lock=锁;
    }
    @凌驾
    公开募捐{
    lock.lock();
    添加(“你好”);
    lock.unlock();
    }
    }
    
    这些字符串正在调用
    IllegalMonitorStateException

    lock.wait
    抛出
    IllegalMonitorStateException
    。为什么?

    事实上,没有这样的界线

    但是,有一行调用
    list.wait()
    。那就是你的问题的原因

    要在对象上调用
    wait()
    ,必须首先持有该对象上的基本互斥锁。您只能使用
    synchronized
    获得这种锁。(一个
    synchronized
    方法或一个
    synchronized
    块。)

    就你而言:

    • 您正在调用
      列表
      实例上的
      等待
    • 您正在锁定
      Lock
      实例
    • 您持有的
      对象的锁类型不正确。请稍候。您持有的是
      锁,而不是原始互斥锁
    所以。。。如果要在
    实例上执行与等待和通知等效的操作,则需要执行的操作是调用
    锁.newCondition()
    以获取
    条件
    对象。然后你就这样使用它:

    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
    }
    
    (可以使用任何对象作为锁,但最好使用隐藏的对象,并且不会被任何其他代码锁定。)



    总之,可以将基本互斥锁与
    同步
    对象一起使用。等待
    对象。通知*
    ,或者将
    锁与
    锁一起使用。获取
    锁。释放
    条件。等待
    条件。信号
    。不要尝试混合使用两种类型的锁定和条件变量。

    您的意思是锁定的工作方式与同步块不同吗?