Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在并发Java程序中非标准使用wait notify_Java_Multithreading_Design Patterns_Wait_Notify - Fatal编程技术网

在并发Java程序中非标准使用wait notify

在并发Java程序中非标准使用wait notify,java,multithreading,design-patterns,wait,notify,Java,Multithreading,Design Patterns,Wait,Notify,我非常熟悉wait()/notify()信令方案在Java中的工作原理。然而,我意识到,我所看到的少数使用模式是该方案的变体,或者是一个应用程序的实现。我还看到了一些众所周知的并发问题的实现,例如用餐哲学家使用wait/notify,但显然是出于教学目的 此外,所有方案都遵循了良好的建议,即始终在循环内调用wait(),并且只在传递循环后更改某些共享变量,如下代码所示: synchronized(mon) { // #CP1 - Do not change variables here

我非常熟悉
wait()/notify()
信令方案在Java中的工作原理。然而,我意识到,我所看到的少数使用模式是该方案的变体,或者是一个应用程序的实现。我还看到了一些众所周知的并发问题的实现,例如用餐哲学家使用wait/notify,但显然是出于教学目的

此外,所有方案都遵循了良好的建议,即始终在循环内调用
wait()
,并且只在传递循环后更改某些共享变量,如下代码所示:

synchronized(mon) {

   // #CP1 - Do not change variables here

   while !(mycondition) {
      try{
         // #CP2 Do not change variables here
         mon.wait();
      } catch(catch (InterruptedException e) {  e.printStackTrace(); }
   }

   // Condition satisfied - Now you can change!      
   makeOperation();

   // Tell others that you're done and exit
   mon.notifyAll();
}
我的问题是:
wait()/notify()?你是否曾以非正统的方式使用过它?为什么?以下是一些更为具体的问题:

  • 您是否见过在退出循环之前更改共享变量的实现?在我的示例中,是否有理由在控制点
    #CP1
    #CP2
    中分配某些内容
  • 在某些情况下,您是否选择使用
    notify()
    而不是
    notifyAll()
    ?虽然可能会提高性能,但您非常确定这不会导致死锁吗?为什么?
  • 是否存在一些复杂的场景,其中等待条件
    mycondition
    取决于多个线程,例如
    mycondition=a_ready&&b_ready&&c_ready
  • 当然。一个例子是,在CP1,你可以保留一份“等待名单”。我不确定我是否能想到您可能在#CP2改变的共享状态,因为通常情况下,while循环只有在“虚假”唤醒的情况下才会出现(即,您被唤醒,但实际上不应该被唤醒)。另外,处理InterruptedException通常是个坏主意,因为它不允许关闭线程(虚假唤醒与获取InterruptedException不同)
  • 如果您知道只有一个服务员将继续,您可以使用notify而不是notifyAll。如果有大量等待的线程,这可能会更有效。但是,在使用notify时有一些需要特别小心的注意事项。服务员可能会收到通知并被打断,因此您对InterruptedException的处理需要重新通知(这样通知就不会丢失)。这意味着,即使你只想叫醒一名服务员,你也需要正确处理可能叫醒不止一名服务员的情况。通常,您必须确保您的代码正确地导致另一个线程继续运行,否则可能会导致死锁
  • 当然。您可以有一个标志指示给定线程应继续,另一个标志指示所有线程应中止(系统关闭或算法中止)

  • 我认为在现代,使用
    wait
    notify
    是控制线程的非标准方式。可以说,如果没有边缘效应,
    java.util.concurrent
    工具就无法完成任何事情。@OldCurmudgeon:我同意
    wait
    notify
    是非标准的,因为
    java.util.concurrent
    。但是是否有人在使用
    java.util.concurrent.locks.Condition
    ,它是
    wait/notify
    的高级替代品?如果是这样,问题仍然存在。我认为将自己限制在
    条件下是无效的。生产者/消费者体系结构现在可以通过处理一对多、多对一和一对一数据流的各种
    BlockingQueue
    类完美完成。除此之外,您还可以进入
    CyclicBarrier
    、atomics甚至
    ForkJoinPool
    来实现几乎任何目标。您还可以获得多种其他好处,如
    期货
    线程池
    s。试图将旧的
    wait/notify
    j.u.concurrent
    的丰富性进行比较是在比较粉笔和奶酪。确实,你对
    j.u.current
    提供的设施有一点看法。