gpt4 book ai didi

c# - 这种对 Monitor.Wait/Pulse 的使用是否存在竞争条件?

转载 作者:行者123 更新时间:2023-11-30 19:33:58 27 4
gpt4 key购买 nike

我有一个简单的生产者/消费者场景,其中只有一个项目被生产/消费。此外,生产者在继续之前等待工作线程完成。我意识到这种方式避免了多线程的全部意义,但请假设它确实需要这样(:

这段代码无法编译,但我希望你明白了:

// 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)。我只是很好奇这是否是一个问题。

最佳答案

不能保证消费者会在另一个生产者之前进入等待或就绪队列。
C# 和 Java 风格的监视器在 Wikipedia, under "Implicit condition monitors" 中有描述。 .
Monitor 中发生的事情的一个很好的概述(取自 this 优秀网站): alt text

"Could the Wait() on Line C allow another thread at Line A to obtain the lock and overwrite m_data before the worker thread even gets to it?"

假设 SetData() 被两个生产者线程 P1P2 调用。
消费者线程 C1 也已启动。
P1P2C1都进入就绪队列。
P1先获取锁。
等待队列为空,B 行 上的Pulse() 无效。
P1C行等待,所以它被放入等待队列。
就绪队列中的下一个线程获取锁。
它同样可以是 P2C1 - 在第一种情况下,断言失败。
你有一个竞争条件。

"Supposing that doesn't happen, and the worker thread processes the original m_data, and eventually makes its way to Line F, what happens when that Pulse() goes off?"

它将一个服务员从等待队列移动到就绪队列。
锁由发出 Pulse() 的线程持有。
在脉冲线程释放锁后,通知线程将有机会获取锁(就绪队列中可能已经有其他线程)。
来自 MSDN, Monitor.Pulse() :
“当前拥有指定对象锁的线程调用此方法以向排队的下一个线程发出锁信号。在接收到脉冲后,等待线程被移至就绪队列。当调用 Pulse 的线程释放锁,就绪队列中的下一个线程(不一定是被脉冲的线程)获取锁。”

"Will only the thread waiting on Line C be able to get the lock? Or will it be competing with all the other threads waiting on Line A as well?"

就绪队列中的所有线程“竞争”下一个锁。
他们是直接到达那里还是通过 Pulse() 从等待队列到达那里并不重要。

“队列”可以通过其他方式实现。 (不是队列这样的数据结构)。
这样,Monitor 实现可能无法保证公平性 - 但可能具有更高的整体吞吐量/性能。

关于c# - 这种对 Monitor.Wait/Pulse 的使用是否存在竞争条件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2631658/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com