С этой страницы :
Каждое приобретение блокировки может вызвать исключение. Будьте готовы к этому.
Большинство блокировок лениво выделяют событие, если обнаружение блокировки сталкивается с конфликтом, включая мониторы CLR. Это распределение может завершиться ошибкой в условиях низкого ресурса, что приведет к появлению OOM от входа в замок. (Обратите внимание, что типичная неблокирующая спин-блокировка не может выйти из строя с OOM, что позволяет использовать ее в некоторых сценариях с ограниченными ресурсами, например внутри CER.) Точно так же хост, такой как SQL Server, может выполнять обнаружение взаимоблокировок и даже прерывать эти взаимоблокировки с помощью генерация исключений, которые происходят из оператора Enter, проявляющегося как исключение System.Runtime.InteropServices.COMException.
Часто не так много можно сделать в ответ на такое исключение. Но код, чувствительный к надежности и безопасности, который должен иметь дело с ошибками, должен учитывать этот случай. Нам бы хотелось, чтобы в этом случае можно было разумно реагировать на взаимные блокировки хоста, но большая часть кода библиотеки не может интеллектуально развернуть безопасную точку в стеке, чтобы она могла откатиться и повторить операцию. В типичном стеке просто слишком много кросс-библиотечного перемешивания. Вот почему приобретение монитора на основе тайм-аута с TryEnter, как правило, является плохой идеей для предотвращения тупиков.
Итак, как вы можете прочитать, кажется, что в условиях ограниченных ресурсов мы можем получить исключения из метода Enter, который Monitor использует внутренне. Lock (o).
Так что, возможно, ваше решение похоже на вращение?
{
uint iters = 0;
while (!cond) {
if ((++iters % 50) == 0) {
// Every so often we sleep with a 1ms timeout (see #30 for justification).
Thread.Sleep(1);
} else if (Environment.ProcessorCount == 1) {
// On a single-CPU machine we yield the thread.
Thread.Sleep(0);
} else {
// Issue YIELD instructions to let the other hardware thread move.
Thread.SpinWait(25);
}
}
}
Где может быть какой-то cond
private volatile int cond = 0
используется, например, с Interlocked.CompareExchange, где вы меняете, например, на. Thread.Current.ManagedThreadID или что-то еще, отличное от нуля?