Это отдельный вопрос, основанный на этом вопросе . Напомним, что у меня есть две функции, которые управляют счетчиком, и функция OnTimer, которая срабатывает с регулярным интервалом. Я хочу, чтобы, если / когда вызывался OverwriteCount, IncrementCount не мог быть выполнен, пока не будет выполнена функция таймера.
Предлагаемое решение было:
private int _myCount = 0;
private readonly object _sync = new object();
private ManualResetEventSlim mre = new ManualResetEventSlim(initialState: true);
void IncrementCount()
{
mre.Wait(); // all threads wait until the event is signaled
lock (_sync)
{
_myCount++;
}
}
void OverwriteCount(int newValue)
{
lock (_sync)
{
mre.Reset(); // unsignal the event, blocking threads
_myCount = newValue;
}
}
void OnTimer()
{
lock (_sync)
{
Console.WriteLine(_myCount);
mre.Set(); // signal the event
}
}
ManualResetEventSlim пытается гарантировать, что как только OverwriteCount () откажется от события, любые модификации _myCount должны ждать, пока OnTimer () не выполнится.
Задача :
- Скажите, что поток A входит в IncrementCount () и передает ожидание события () - начальное состояние ManualResetEvent уже сигнализируется.
- Затем поток B запускается и выполняет все функции OverwriteCount ().
- Поток A затем продолжает, получая блокировку и увеличивая _myCount.
Это нарушает мою цель, поскольку _myCount изменится после вызова OverwriteCount () до запуска OnTimer.
Отклоненная альтернатива : Я могу переместить mre.Wait () в пределах блокировки (_sync), но это может привести к тупиковой ситуации. Если поток A вызывает IncrementCount () и блокирует ожидание, никакие другие потоки не могут получить блокировку для ее снятия.
Вопрос : Нужен ли другой примитив синхронизации для достижения моей цели? Или я ошибаюсь из-за проблем безопасности потоков?