Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/397.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_Wait_Notify - Fatal编程技术网

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

Java 为什么wait()和notify()不在特殊类中?,java,wait,notify,Java,Wait,Notify,为什么wait、notify和notifyAll方法都放在Object中,而不是放在某个单独的类中 注意,这个问题不是关于将它们移动到线程类,我只是想知道为什么它们丢弃对象,而不是一些新的监视器类 我认为这种想法有以下缺点: 我们将无法将“用于其他目的”字段用作监视器。但这似乎符合模块化原则 同步方法现在需要对生成的隐藏字段(如闭包)进行一些黑客攻击,因为这个和类成为无效监视器 因此,我们可以从每个对象中移除5种方法,但有点麻烦。是否?因为每个对象都可以充当监视器 真正的答案是,这是一个错误

为什么
wait
notify
notifyAll
方法都放在
Object
中,而不是放在某个单独的类中

注意,这个问题不是关于将它们移动到
线程
类,我只是想知道为什么它们丢弃
对象
,而不是一些新的
监视器

我认为这种想法有以下缺点:

  • 我们将无法将“用于其他目的”字段用作监视器。但这似乎符合模块化原则
  • 同步方法现在需要对生成的隐藏字段(如闭包)进行一些黑客攻击,因为
    这个
    成为无效监视器

因此,我们可以从每个对象中移除5种方法,但有点麻烦。是否?

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

真正的答案是,这是一个错误,最终在创建类时得到了承认,它完全符合您的预期。(虽然由于它是一个对象,但您可能会意外地在它上调用
wait()
,而不是
wait()
,结果会很滑稽……)

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

因此,您可以这样做,例如:

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

class B {
   void foo() {
      synchronized((Integer)42) { 
          ...
      }
   }
}
如果对象是不可变的,那么每次为
42
返回相同的装箱整数应该不是问题。但它不是,它有一个可变的状态:它的监视器,使这种同步成为可能。特别糟糕的是,您在两段代码之间创建了一个互斥体,从表面上看,互斥体似乎是独立的。

1)等待和通知不仅仅是普通的方法或同步实用程序,而不仅仅是Java中两个线程之间的通信机制。如果这个机制不能通过任何java关键字(如synchronized)使用,那么对象类就是使它们对每个对象都可用的正确位置。记住,synchronized和wait notify是两个不同的区域,不要混淆它们是相同的或相关的。Synchronized是在两个线程之间的通信机制wait和notify的同时,提供互斥性,保证Java类的线程安全性,比如争用条件

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

3) 在Java中,为了进入代码的关键部分,线程需要锁并等待锁,它们不知道哪个线程持有锁,而只是知道锁被某个线程持有,它们应该等待锁,而不是知道哪个线程在同步块中并要求它们释放锁。这种类比适用于Java中对象类而非线程上的等待和通知


使用ref:

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

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


如果所有的同步都在一个单独的类中,它将不起作用。

我只是想知道为什么它们会丢弃对象,而不是一些新的监视器类。
-从概念上讲,它们是在内部进行的,但是监视器对于每个对象都是唯一的。查看重复答案(即使它指的是
线程
)@biziclop。当Per Brinch Hansen看到Java最初的并发结构时,他写道“很明显,我的努力是徒劳的”。它们似乎是从UNIX不可爱的
sleep/wakeup()
内部借用来的。“因此,我们可以从每个对象中移除5个方法,但有点麻烦”从技术上讲,这些方法只存在一次,而不是每个实例都存在一次。因为Java没有多重继承,所以不能简单地混合这些功能,当然,我说错了。我的意思是,在用户看来,将是5个额外的方法,这不是很方便是的,但问题是为什么不有一个单独的类。了不起的答案。我希望添加额外的+1,例如缓存Integers@Martoon作为一个练习,我写了一篇文章,利用这篇文章相互交流。真正可怕的是,无论你把它们放在同一个虚拟机中的什么地方,它们都能工作,例如,在同一个容器中的两个独立的web应用程序。是的,这是我列出的第一个缺点。但是以这种方式思考会导致我们将
ReentrantLock.lock()
unlock()
StringBuilder.append()
,我不知道还有什么,移动到
对象
类,这似乎不是一个好的转折点。我的意思是,
对象
类不是专门用于同步的,我不认为这是一个优势。由于安全的同步方式不是在公开可见的对象上进行同步,因此大多数情况下,您最终都会在
private final
字段中创建一个专用锁对象。
private final Object mySpecialMonitor = new Object();

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