【问题标题】:Automatic notify()/notifyAll() on leaving a synchronized block [closed]离开同步块时自动 notify()/notifyAll() [关闭]
【发布时间】:2013-04-08 19:08:21
【问题描述】:

我一直在考虑向 Java 语言架构师发送提案。

在同步块中

synchronized(lock) {

// If there is no notification before this point
// <--- implicitly put here // lock.notifyAll(); // OR // lock.notify();  
}

线程离开同步块后,不能再调用 lock.notifyAll() / lock.notify() 而不发生异常。

忘记通知其他线程监视器持有者可能会永远让他们(其他线程)等待(除非他们在他们的等待方法中设置了一些超时)。

synchronized(lock) {

     lock.wait(); //<--- this thread may forever freeze here
}

我无法想象这种行为(在同步块末尾插入隐式通知,当没有显式通知时)是不可取的情况。

同样的方法可以应用于同步方法。


可以有不同的方式来(技术上)实现这种行为,例如:

@autonotify
synchronized(lock) {
...
}

@autonotify
public void synchronized doSomething() {
...
}

或者:

@autonotifyAll
synchronized(lock) {
...
}

@autonotifyAll
public void synchronized doSomething() {
...
}

或者 - 使自动通知成为默认行为,但保留抑制它的能力,例如:

@suppressautonotify
synchronized(lock) {
...
}

@suppressautonotifyAll
public void synchronized doSomething() {
...
}

你怎么看?反对?

将接受支持或反对提案的最佳评论作为答案。

【问题讨论】:

  • 在很多情况下,这样做会导致错误(或者至少在未满足等待条件时会导致不需要的唤醒)。并非所有同步都已完成以通知监视器。

标签: java multithreading thread-safety


【解决方案1】:

自动或默认执行此操作是一个很大的禁忌。在许多情况下,您在锁上同步而不希望在同步块结束时通知。这样做会破坏大量现有程序。

为什么要使用@autonotifyAll,而不是在同步块末尾使用简单的lock.notifyAll()。如果您忘记拨打lock.notifyAll(),您就有很多机会忘记@autonotifyAll。而且它会降低可读性和一致性。

无论如何,最佳实践是避免使用这些非常低级的方法,而使用更高级别的抽象,如阻塞队列、倒计时锁存器、信号量等。

如果我必须做出决定,您的建议将被拒绝。

【讨论】:

  • 我也是这么想的 - 将行为更改为 auto-nofity 会破坏现有应用程序。可能这是不这样做的主要论据。
  • 但是,问题仍然存在——你能想象在没有 notify() 或 notifyAll() 的情况下离开同步块的情况是合理的吗?我不能。
  • 是的,在 99% 的情况下,仅当您同步以确保互斥时。例如查看 java.util.Vector 的来源。它的所有方法都是同步的,内部对notify或notifyAll的调用为零。
  • autonotifyAll 和 lock.notifyAll() 的区别在于,如果抛出异常,lock.notifyAll() 可能会被跳过,但 autonotifyAll 可能会以类似于 finally 块行为的方式实现。
  • @AlexKreutznaer 已经有一种方法可以进行同步(锁定){} 最后{}。它与您想要的语法略有不同:synchronized(lock) { try {...} finally {...} }
【解决方案2】:

Object.waitObject.notify/All 被认为是相当低级的同步机制;大多数时候,您会想要使用更高级别的构造,例如在java.util.concurrent 或其子包中找到的构造。如果您的用例足够微妙或特殊,以至于您需要使用这些 Object 方法,而不是 JDK 人员为您构建、测试和优化的高级工具——那么,您可能想要完全控制,并且希望(对于您的代码的用户)您可以处理它。

打个开车的比喻,这个问题相当于买了一辆带手动变速箱而不是自动变速箱的汽车,然后在你想换档时让汽车制造商自动为你工作离合器。

【讨论】:

  • 完全跑题了,但今天市场上的很多汽车都有“换挡拨片”,可以做到这一点! ;-) (虽然它们不是手动变速器)
猜你喜欢
  • 2019-02-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-02-19
  • 1970-01-01
  • 1970-01-01
  • 2011-04-17
相关资源
最近更新 更多