我有一个简单的生产者/消费者场景,其中只有一个项目正在生产/消费。此外,生产者在继续之前等待工作线程完成。我意识到这种方式消除了多线程的全部意义,但请假设它确实需要这样(:
这段代码无法编译,但我希望你能明白:
// m_data is initially null
// This could be called by any number of producer threads simultaneously
void SetData(object foo)
{
lock(x) // Line A
{
assert(m_data == null);
m_data = foo;
Monitor.Pulse(x) // Line B
while(m_data != null)
Monitor.Wait(x) // Line C
}
}
// This is only ever called by a single worker thread
void UseData()
{
lock(x) // Line D
{
while(m_data == null)
Monitor.Wait(x) // Line E
// here, do something with m_data
m_data = null;
Monitor.Pulse(x) // Line F
}
}
这是我不确定的情况:
假设许多线程使用不同的输入调用 SetData()。其中只有一个会进入锁内,其余的将在 A 行被阻塞。假设进入锁内的那个设置m_data并进入 C 行。
问题:C 行上的 Wait() 是否允许 A 行上的另一个线程在工作线程到达之前获得锁并覆盖m_data ?
假设这没有发生,并且工作线程处理原始m_data并最终到达 F 行,那么当 Pulse() 关闭时会发生什么?
只有在 C 行等待的线程才能获得锁吗?或者它是否会与在线 A 上等待的所有其他线程竞争?
本质上,我想知道 Pulse()/Wait() 是否特别“在后台”相互通信,或者它们是否与 lock() 处于同一级别。
这些问题的解决方案(如果存在)当然是显而易见的——只需用另一个锁包围 SetData()——比如 lock(y)。我只是好奇这是否甚至是一个问题。