Wait()和Notify()概念 – Javamultithreading

class Q { volatile boolean valueSet = false; volatile int n; synchronized int get () { if ( !valueSet ) { try { wait(); } catch ( InterruptedException e ) { System.out.println( "InterruptedException caught" ); } } System.out.println( "Got: " + n ); valueSet = false; notify(); return n; } synchronized void put ( int n ) { if ( valueSet ) { try { wait(); } catch ( InterruptedException e ) { System.out.println( "InterruptedException caught" ); } } this.n = n; valueSet = true; System.out.println( "Put: " + n ); notify(); } } class Producer implements Runnable { Q q; Producer ( Q q ) { this.q = q; new Thread( this, "Producer" ).start(); } public void run () { int i = 0; while ( true ) { q.put( i++ ); } } } class Consumer implements Runnable { Q q; Consumer ( Q q ) { this.q = q; new Thread( this, "Consumer" ).start(); } public void run () { while ( true ) { q.get(); } } } class PCFixed { public static void main ( String args[] ) { Q q = new Q(); new Producer( q ); new Consumer( q ); System.out.println( "Press Control-C to stop." ); } } 

我无法理解这是如何工作的。 以此流程为例。 生产者输入put方法并调用notify()。 如果没有消费者调用wait()怎么办? 此外,一旦生产者调用notify(),当生产者还没有放弃监视器时,消费者如何进入方法get()? 请帮帮我。

我假设顶部的类是Q,它缺少一些代码。 无论如何,一般的想法是boolean valueSetwait() / notify()调用串联工作。

如果消费者已经开始等待,他已经通过synchronized get()方法获取了对Q实例的锁定,然后在等待时释放它。

如果消费者尚未开始等待,则生产者可能锁定Q实例,因为put()方法在同一个锁上同步。 一旦生产者退出锁定,他就会调用notify() 并将valueSet布尔值设置为true

消费者对get()的下一次调用将在尝试等待之前读取布尔值,注意那里的某些内容,获取n的内容并执行所需的任何工作。 如果没有设置该值,意味着在消费者缺席的情况下没有任何内容,他会wait()锁定新工作,下一个notify()将唤醒他。

更新

在评论的场景中,你基本上是在询问完全相同的情况,但反之亦然。 同样的逻辑也适用。

消费者当前正在等待,生产者调用notify() 。 生产者当前拥有锁定,并将在方法持续时间内继续持有锁定。 所有notify()都会让当前正在等待锁定的其他线程知道,当锁定被释放时,它可以尝试获取锁定并继续执行。 在这种情况下,只有一个其他线程,但如果有多个线程,那么它只会选择一个(唤醒所有人,应该调用notifyAll() )。

  1. 生产者退出方法,释放锁定。
  2. 消费者醒来并取消锁定。

此时,关于生产者是否已经出现并且当前正在等待锁定还是尚未进入该方法,这是不明确的。 布尔标志和wait() / notify()的相同串联也适用于此。

在消费者通过退出方法释放锁之前,它将boolean标志设置为false并调用notify()

如果生产者当前已经在等待锁定,则调用notify()会让它知道它可以在锁定释放时唤醒并继续。

如果生产者没有等待wait()调用,它必须在方法之外(可能等待输入方法并以此方式获取锁定)。 当使用者退出方法并释放锁时,生产者获取它并检查布尔标志。 它被设置为false,因此生产者不会尝试调用 wait()并仅关闭其值,设置布尔标志并调用notify()

  1. 如果没有消费者调用wait()怎么办?
    • 该消息将丢失
  2. 一旦生产者调用notify(),当生产者还没有放弃监视器时,消费者如何进入方法get()?
    • 它会死锁 – 阻塞直到监视器被重新发布。

我会试着理解它是如何工作的。 例如, Producer已进入put()方法,并看到监视器是空闲的,他可以执行put动作。 当他在这里完成他的工作时,来自Consumer并尝试执行get()动作。 但是他失败了,因为监视器已经被Producer占用,所以他调用wait()意味着他被阻塞在那行代码中等待其他一些线程调用notify() 。 这里的诀窍是,在他被告知监视器再次空闲之前,他再也不会调用get() ,这意味着他不再执行任何空循环。 因此,当Producer完成他的工作时,他调用notify()并且Consumer恢复他离开的地方。 我知道起初有点难以理解,也有点难以解释,但是当你这样做时,你会发现这些都是非常简单和强大的东西。 祝你好运!