私は単純な生産者/消費者シナリオを持っており、生産/消費されているアイテムは1つだけです。また、プロデューサーはワーカースレッドが終了するのを待ってから続行します。この種のマルチスレッド化のポイント全体が不要になることは理解していますが、実際にはこのようにする必要があると想定してください(:
このコードはコンパイルされませんが、次のようなアイデアが得られることを願っています。
// 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()を呼び出すと仮定します。そのうちの1つだけがロック内に入り、残りはラインAでブロックされます。ロック内に入ったものがm_dataを設定し、ラインCに到達するとします。
質問:行CのWait()は、行Aの別のスレッドがロックを取得し、ワーカースレッドがそれに到達する前にm_dataを上書きできるようにすることができますか?
それが起こらず、ワーカースレッドが元のm_dataを処理し、最終的にラインFに到達すると仮定すると、そのPulse()がオフになるとどうなりますか?
ラインCで待機しているスレッドのみがロックを取得できますか?それとも、ラインAで待機している他のすべてのスレッドとも競合しますか?
基本的に、Pulse()/ Wait()が特別に「内部」で相互に通信するのか、それともlock()と同じレベルにあるのかを知りたいです。
もちろん、これらの問題の解決策は明らかです。SetData()を別のロック(たとえば、lock(y)で囲むだけです)。そもそも問題なのか気になります。