Этот код не компилируется, но я надеюсь, что вы поняли идею:
Код: Выделить всё
// 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.
Вопрос: может ли функция Wait() в строке C позволить другому потоку в строке A получить блокировку и перезаписать m_data еще до того, как рабочий поток доберется до нее?
Предположим, что этого не происходит, и рабочий поток обрабатывает исходные m_data и в конечном итоге достигает строки F, что произойдет, когда сработает Pulse()?
Будет только поток, ожидающий в строке C, сможет получить блокировку? Или он тоже будет конкурировать со всеми остальными потоками, ожидающими на линии A?
По сути, я хочу знать, взаимодействуют ли Pulse()/Wait() друг с другом специально «под капотом» или они находятся на одном уровне с lock().
Решение этих проблем, если они существуют, конечно, очевидно — просто окружите SetData() другой блокировкой — скажем, lock(y).
Мне просто интересно, является ли это вообще проблемой.
Подробнее здесь: https://stackoverflow.com/questions/263 ... -condition
Мобильная версия