在Java中使用synchronized令人困惑:模式还是反模式?

在Java中使用synchronized令人困惑:模式还是反模式?,java,multithreading,synchronization,synchronized,Java,Multithreading,Synchronization,Synchronized,我正在为一个我不拥有的Java产品的变更做代码审查。我不是Java专家,但我强烈怀疑这是毫无意义的,并且表明了对同步工作原理的根本误解 synchronized (this) { this.notify(); } 但我可能错了,因为Java不是我的主要游乐场。也许这是有原因的。如果您能告诉我开发人员的想法,我将不胜感激。如果您仍然想使用内部锁,这通常不是一种反模式。有些人可能认为这是一种反模式,因为来自java.util.concurrent的新显式锁更细粒度 但是你的代码仍然有效。例

我正在为一个我不拥有的Java产品的变更做代码审查。我不是Java专家,但我强烈怀疑这是毫无意义的,并且表明了对同步工作原理的根本误解

synchronized (this) {
    this.notify();
}

但我可能错了,因为Java不是我的主要游乐场。也许这是有原因的。如果您能告诉我开发人员的想法,我将不胜感激。

如果您仍然想使用内部锁,这通常不是一种反模式。有些人可能认为这是一种反模式,因为来自
java.util.concurrent
的新显式锁更细粒度


但是你的代码仍然有效。例如,当阻塞操作成功并且应该通知另一个等待的线程时,可以在阻塞队列中找到这样的代码。但是请注意,并发性问题高度依赖于用法和周围的代码,因此您的简单代码片段没有那么大的意义。

这当然不是毫无意义的,您可以让另一个线程引用包含上述代码的对象

synchronized(foo) {
    foo.wait();
}
为了在事情发生时被唤醒。不过,在许多情况下,在内部/私有锁对象上进行同步被认为是一种良好的做法,而不是在
上进行同步


但是,仅在同步块中执行.notify()可能是非常错误的-通常需要做一些工作,并在完成时发出通知,这在正常情况下也需要针对其他线程以原子方式完成。我们必须看到更多的代码来确定它是否真的错了。

的Java API文档声明该方法“应该只由作为该对象监视器所有者的线程调用”。因此,根据周围环境的不同,使用可能是合法的。

这很好。根据报告:

此方法只能由作为此对象监视器所有者的线程调用


如果这就是synchonized块中的全部内容,那么它是一个反模式,同步的要点是在块内执行某些操作,设置一些条件,然后调用
notify
notifyAll
来唤醒一个或多个等待的线程

使用“等待并通知”时,必须使用条件变量,请参阅:

注意:始终在测试等待条件的循环中调用wait。不要假设中断是针对您正在等待的特定条件,或者该条件仍然为真

您不应该假设您收到通知仅仅是因为线程从对象#wait的调用中退出,原因有多种:

  • 调用具有超时值的wait版本时,无法知道等待是由于收到通知而结束还是由于超时而结束

  • 您必须考虑线程在没有收到通知的情况下从等待中醒来的可能性(“虚假唤醒”)

  • 接收通知的等待线程仍然必须重新获取它在开始等待时放弃的锁,这两个事件没有原子链接;在收到通知和重新获取锁之间的时间间隔内,另一个线程可以操作并可能更改系统的状态,从而使通知现在无效

  • 您可能会遇到这样的情况:通知线程在任何线程等待之前执行操作,因此通知无效。假设一个线程在另一个线程通知之前进入等待是危险的,如果你错了,等待的线程将无限期挂起


因此,通知本身还不够好,当wait/notify API没有提供足够的信息让您知道发生了什么时,您最终会猜测是否发生了通知。即使通知线程正在执行的其他工作不需要同步,更新条件变量也需要同步;同步块中应至少更新共享条件变量

我认为这更适合阅读材料:您是否想知道在调用
notify()
之前是否需要同步?线程在调用
notify()
时必须持有对象的监视器,因此这通常是必需的。啊,不知道codereview。谢谢,谢谢你给克莱莫尔的链接。它提供了比我想象的更多的上下文。这就是我所想的,但似乎有时候你可能想要同步。这肯定不是真的。也许在通知之前正在做的事情不需要同步。细粒度同步没有坏处,这通常是一件好事。一个简单的例子可能是后台线程正在等待用户单击按钮(通过等待对象)。当Swing通知ActionListener时,它可以使用上面的代码执行通知。@如果条件在没有防护的情况下更新,Mark听起来非常危险;检查条件的另一个线程可以看到不一致的状态。回想起来似乎很明显。现在我需要弄清楚这一切是如何工作的。好吧,我找不到他在哪里调用这个。wait(),所以我已经发送了反馈,询问这是否真的有必要。在正确使用API时,“很好”。但是OP在问什么,它是模式还是反模式。