离开同步块时自动notify()/ notifyAll()

时间:2013-04-08 19:08:22

标签: java multithreading thread-safety

我一直在考虑向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() {
...
}

你怎么看?异议?

赞成或反对该提案的最佳评论将被接受为答案。

2 个答案:

答案 0 :(得分:7)

自动或默认执行此操作是一个很大的禁忌。在许多情况下,您在锁上进行同步而不想在同步块的末尾进行通知。这样做会打破很多现有的程序。

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

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

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

答案 1 :(得分:0)

Object.waitObject.notify/All被认为是同步的低级别机制;大多数情况下,您需要使用更高级别的结构,如java.util.concurrent或其子包中的结构。如果您的用例非常微妙或特殊,您需要使用这些Object方法而不是JDK人员为您构建,测试和优化的更高级别的工具 - 那么,您可能需要完全控制,并希望(对于您的代码的用户),您可以处理它。

使用驾驶比喻,这个问题相当于购买带有手动变速器而非自动变速器的汽车,然后要求汽车制造商在您想要换档时自动为您操作离合器。