Fra*_*fka 9 java multithreading synchronization notify
想象一下,你有一个典型的Java生产者 - 消费者模式.要想要使用更高效,notify()而不是notifyAll()在将新元素添加到队列时.如果两个生产者线程调用notify,是否可以保证唤醒两个不同的等待消费者线程?或者可能是两个notify()在彼此之后不久被解雇导致同一个comsumer线程排队等待两次唤醒?我找不到该部分是描述这是如何工作的API.java是否有一些原子内部操作来唤醒线程一次?
如果只有一个消费者在等待,那么第二个通知将会丢失,这没有问题.
Gra*_*ray 13
我的答案有一些具体的实施信息.它基于我对Sun JVM和其他线程库行为的工作知识.
如果两个生产者线程调用notify,是否可以保证唤醒两个不同的等待消费者线程?
不它不是.无法保证会有任何消费者醒来.保证的是,如果有2个线程在等待,那么将有2个不同的线程放入运行队列.
或者可能是两个
notify()在彼此之后不久被解雇导致同一个comsumer线程排队等待两次唤醒?
notify()不会.两次调用不会导致相同的消费者线程排队两次.但是,它可能导致一个线程被唤醒,并且可能没有其他线程在等待,因此第二个notify()调用可能什么都不做.当然线程可能已经被唤醒然后再次等待,所以第二次notify()调用就这样,但我不认为这就是你所要求的.
java是否有一些原子内部操作来唤醒线程一次?
是.该Thread代码具有许多同步点.一旦线程被通知,它就会被移出wait队列.未来的调用notify()将调查wait队列而不是找到线程.
更重要的一点.对于生产者/消费者模型,始终确保您在while循环中测试条件.原因是有消费者的竞争条件被锁定但没有等待条件.
synchronized (workQueue) {
// you must do a while here
while (workQueue.isEmpty()) {
workQueue.wait();
}
workQueue.remove();
}
Run Code Online (Sandbox Code Playgroud)
Consumer1可能在等待workQueue. Consumer2可能会被阻止synchronized但在运行队列中.如果事情被放入workQueue和workQueue.notify()被调用. Consumer2现已投入运行队列,但背后 Consumer1谁在那里第一次.这是一种常见的实现方式.所以,Consumer1去在将删除的项目workQueue是Consumer2被通报的. Consumer2必须再次测试是否workQueue为空,否则remove()将抛出,因为队列再次为空.有关比赛的更多详情,请参见此处.
同样重要的是要意识到已经记录了虚假的while唤醒,因此循环可以防止线程在没有wait()调用的情况下被唤醒.
所有这些说,如果您可以通过使用BlockingQueue其他答案中建议的减少您的生产者/消费者代码,那么您应该这样做.该BlockingQueue代码已经解决了所有这些问题.
| 归档时间: |
|
| 查看次数: |
2647 次 |
| 最近记录: |