Multithreading scala notify()与notifyAll()的比较
给出了scala中生产者-消费者问题的以下实现Multithreading scala notify()与notifyAll()的比较,multithreading,scala,Multithreading,Scala,给出了scala中生产者-消费者问题的以下实现 class PC { var buffer = null.asInstanceOf[Int] var set = false def produce(value: Int) = synchronized { while (set) wait() buffer = value set = true notify() } def consume: Int = synchronized { wh
class PC {
var buffer = null.asInstanceOf[Int]
var set = false
def produce(value: Int) = synchronized {
while (set) wait()
buffer = value
set = true
notify() }
def consume: Int = synchronized {
while (!set) wait()
val result = buffer
set = false
notify()
return result; }
}
有三件事我不太明白:
这实际上是一个关于Java并发性的问题。Scala并发是建立在Java并发模型之上的,但语法不同,上述语法相当于使用关键字
synchronized
编写同步方法,如下Java代码所示:
public class PC {
public int buffer;
public boolean set;
public synchronized void produce(int value) {
while(set) wait();
buffer = value;
set = true;
notify();
}
public synchronized int def consume {
while(!set) wait();
int result = buffer;
notify();
return result;
}
}
有关Java并发模型的更多详细内容,请阅读。你可能想调查这个问题。例如,您可以使用容量为1的实现相同的功能
回答你的问题:
1。为什么,如果我使用notify而不是notifyAll,我最终会陷入死锁;我应该在哪里使用notifyAll,用于生产或消费?
您可能有一个争用条件(而不是死锁),因为consumer()
中的notify()
是由其他一些使用者线程而不是生产者线程接收的,但这只是一个猜测。至于是使用notify()
还是使用notifyAll()
以及在哪些方法中,一些人建议始终使用notifyAll()
。在本例中,您可以使用notifyAll()
,因为您正在条件while循环中等待—由于的文档中描述的各种原因,您应该始终这样做。但是,您也可以选择在producer()
中使用notify()
作为优化,因为我假设您只希望一个使用者使用缓冲区内容。在当前的实现中,您仍然必须在consume()
中使用notifyAll()
,或者可能会遇到这样的情况,即其中一个消费者收到通知,而不是单个等待生产者,从而导致生产者永远等待
2。我不应该有一个对象,例如lock,并调用lock.synchronized、lock.wait和lock.notify吗?为什么它是这样工作的,不生产和消费有两个不同的显示器关联?为什么来自生产的“通知”通知来自消费的“等待”?
你确实有一把锁。它是对PC
实例的隐式锁定,在Java中,每个对象只有一个监视器,尽管可能有许多入口点。consume()
中的wait()
由product()
中的notify()
通知,因为它们都在等待对同一资源的锁定--PC
实例。如果您想要实现更灵活或更细粒度的锁定,那么您可以使用来自的各种策略,例如
3。监视器在scala中是如何工作的(在我们的例子中)?它是否使用信号并继续策略?在特定条件下,如何将等待队列中的进程移动到可运行队列?每个条件/锁是否都有一个队列(例如lock1.wait、lock2.wait等)。
有关JVM如何执行线程同步的详细描述,请阅读以下内容:。有关同一作者的章节的更多细节,您可以阅读。为什么,如果我使用notify而不是notifyAll,我最终会陷入死锁?
正如您所观察到的,如果只有一个生产者和一个消费者,您所看到的问题就不会发生(因为在这种情况下,notify
完成了您期望它完成的工作,即让下一个生产者/消费者行动)
但是,如果您有多个生产者或消费者,则会出现以下问题:假设有两个生产者和一个消费者。在这种情况下,如果使用notify()
,则必然会发生以下情况:
notify()
notify()
唤醒的生产者现在无限等待,因为消费者永远不会得到通知notifyAll
,则始终会有一个消费者收到通知,因此生产者或消费者会无限期地等待另一方
我不应该有一个对象,例如lock,并调用lock.synchronized、lock.wait和lock.notify吗?
锁定对象是
PC
对象。Scala对象
只是编译器为您生成的类的单例实例。由于您的对象实际上是类对象的类实例,因此它也继承了它的notify
、notifyAll
和wait
方法。p.S.我有一个生产者和多个消费者。尝试使用producer/comsumer,它会更简单。我建议您避免使用wait()和notify(),它们是非常低级的细粒度原语,并使用java.util.concurrent中的内容