#c# #multithreading #locking #critical-section
#c# #многопоточность #блокировка #критический раздел
Вопрос:
У меня есть критический раздел (с использованием lock
области редактирования).
Я бы хотел, чтобы на нем «спал» только последний входящий поток. Следовательно, как только критическая секция заблокирована, каждый входящий поток «завершает» все предыдущие спящие потоки.
Есть ли способ добиться этого с помощью C #?
Спасибо
Комментарии:
1.
lock
используетMonitor
класс под капотом, вы можете попытаться получить желаемое поведение, используяMonitor
илиSemaphore
2. Можете ли вы определить, что должно произойти с другими потоками?
3. @MoB. другие потоки завершаются и собираются GC
Ответ №1:
Механизм, который казался наиболее эффективным для достижения этой цели, заключался в использовании задач, поэтому приведенное ниже решение на самом деле асинхронное, а не синхронное, поскольку таким образом код получился намного проще. Если вам нужно, чтобы это было синхронно, вы можете просто синхронно ожидать выполнения задач.
public class SingleWaiterLock
{
private bool realLockTaken = false;
private TaskCompletionSource<bool> waiterTCS = null;
private object lockObject = new object();
public Task<bool> WaitAsync()
{
lock (lockObject)
{
if (!realLockTaken)
{
realLockTaken = true;
return Task.FromResult(true);
}
if (waiterTCS == null)
{
waiterTCS = new TaskCompletionSource<bool>();
return waiterTCS.Task;
}
else
{
waiterTCS.SetResult(false);
waiterTCS = new TaskCompletionSource<bool>();
return waiterTCS.Task;
}
}
}
public void Release()
{
lock (lockObject)
{
if (waiterTCS != null)
{
waiterTCS.SetResult(true);
waiterTCS = null;
}
else
{
realLockTaken = false;
}
}
}
}
Логическое значение, возвращаемое методом ожидания, указывает, действительно ли вы получили блокировку (если она возвращает true) или были загружены кем-то, кто придет позже (возвращает false). Блокировка должна быть снята (но всегда должна быть снята) только тогда, когда ожидание возвращает значение true.