为什么wait()和notify()不在特殊类中?

时间:2016-02-16 11:32:49

标签: java wait notify

为什么waitnotifynotifyAll方法放在Object中,而不是放在某个单独的类中?

请注意,这个问题并不是要将它们移到Thread课程,我只是想知道为什么他们会丢弃Object,而不是一些新的Monitor课程。

我认为这个想法存在以下缺点:

  • 我们无法将我们的for-other-purpose字段用作监视器。但这似乎与模块化原则一致。
  • 同步方法现在需要对生成的隐藏字段进行一些破解(如在闭包中),因为this<MyClass>.class变为无效的监视器。

因此,我们可以从每个对象中移开5个方法,带点祸患。或者不是?

4 个答案:

答案 0 :(得分:7)

真正的答案是,这是一个错误,最终通过创建Condition类来承认,它完全符合您的期望。 (虽然因为它是一个对象,你可能会意外地在其上调用wait()而不是await(),这会带来欢闹的后果......)

除了您已经列出的内容之外,将监视器绑定到每个对象也使得在Java中无法拥有真正的不可变对象。

所以你可以这样做:

class A {
   void foo() {
      synchronized((Integer)42) {
         ...
      }
   }
}

class B {
   void foo() {
      synchronized((Integer)42) { 
          ...
      }
   }
}

如果对象是不可变的,每次返回42的同一个盒装整数应该不是问题。但它不是,它有一个可变的状态:它的监视器,使这种同步成为可能。在这方面特别邪恶的是你在两段代码之间创建了一个互斥体,它看起来是独立的。

答案 1 :(得分:1)

这样做的一个优点是您可以简单地同步参考而无需为其创建冗余监视器:

synchronized (myList) {
    myList.add(0);
}

VS

private final Object mySpecialMonitor = new Object();

syncronized(mySpecialMonitor) {
    myList.add(0);
}

如果所有同步都在一个单独的类中,它将无效。

答案 2 :(得分:0)

因为每个对象都可以充当监视器。

答案 3 :(得分:0)

1)等待和通知不仅仅是普通方法或同步实用程序,而是它们是Java中两个线程之间的通信机制。如果通过任何java关键字(例如synchronized)无法使用此机制,那么Object类是使它们可用于每个对象的正确位置。记住同步和等待通知是两个不同的区域,不要混淆它们是相同的或相关的。同步是提供互斥并确保Java类的线程安全,如等待和通知是两个线程之间的通信机制。

2)锁定在每个对象的基础上可用,这是在Object类而不是Thread类中声明wait和notify的另一个原因。

3)在Java中为了进入代码的关键部分,线程需要锁定并等待锁定,他们不知道哪些线程持有锁而不知道锁定是否被某个线程保持并且他们应该等待锁定而不是知道同步块中的哪个线程并要求它们释放锁定。这个比喻适合于等待并通知对象类而不是Java中的线程。

使用ref:http://javarevisited.blogspot.in/2012/02/why-wait-notify-and-notifyall-is.html