Паттер блокировки с двойной проверкой - это то, что вам нужно:
Это то, что вам нужно:
class Foo
{
private object someLock = new object();
private object someFlag = false;
void SomeMethod()
{
// to prevent locking on subsequent calls
if(someFlag)
throw new Exception();
// to make sure only one thread can change the contents of someFlag
lock(someLock)
{
if(someFlag)
throw new Exception();
someFlag = true;
}
//execute your code
}
}
В общем, когда вы сталкиваетесь с такими проблемами, пытайтесь следовать хорошо известным шаблонам.как приведенный выше.
Это делает его распознаваемым и менее подверженным ошибкам, так как вы с меньшей вероятностью что-то пропустите при следовании шаблону, особенно когда дело доходит до многопоточности.
В вашем случае первое, если не многосмысла, но часто вы захотите выполнить реальную логику, а затем установить флаг.Второй поток будет заблокирован, пока вы выполняете свой (возможно, довольно дорогостоящий) код.
О втором примере:
Да, это правильно, но не усложняйте его, чем это.У вас должны быть очень веские причины не использовать простую блокировку, и в этой ситуации это делает код более сложным (потому что Interlocked.CompareExchange()
менее известен), ничего не добиваясь (как вы указали, что блокировка меньше против блокировки для установки логического флагав данном случае это не совсем выгодно).