Pergunta

É esse padrão de exclusão mútua tão seguro quanto eu acho que é? Se assim for, o que você chamá-lo?

lock (_lock) {
    if (_flag) return;
    else _flag = true;
}
try {
    //critical code...
}
finally {
    _flag = false;
}

Eu quero garantir a seção crítica, mas sem os outros tópicos acumulando esperando para adquirir o bloqueio. Obviamente, eu certifique-se o sinalizador está definido em nenhum outro lugar. Existe uma maneira melhor?

Foi útil?

Solução

Não, isso não é seguro. Se você quiser garantir mutuamente exclusivas, sem bloquear, você pode usar Monitor.TryEnter:

if (Monitor.TryEnter(lockObj, 0)) {
    // got the lock !
    try {
        // code
    }
    finally { // release the lock
        Monitor.Exit(lockObj);
    }
}

Outras dicas

Você já olhou para Monitor.TryEnter ?

A correção do seu padrão de exclusão mútua depende da _Flag atribuição = false estar atômica. Imagine o que aconteceria se a atribuição pode ser interrompido por outro segmento. Se os resultados intermediários de atribuição poderia ser interpretado como falsa pelo teste, uma atribuição pode causar vários tópicos para entrar na seção crítica.

A correção do padrão de exclusão mútua depende também da ausência de otimizações do compilador que pode reorganizar a ordem das declarações. Imagine um compilador "inteligente" que moveria a atribuição _Flag = false para cima, porque _Flag não é referido no código que está entre (e o código entre não lançar exceções). O compilador poderia otimizar a parte na seção de bloqueio de ler

if(_flag) return;

Ambos os exemplos de por que o padrão poderia falhar são altamente especulativos e eu acho que você está seguro em assumir ele funciona. No entanto, na presença de uma outra opção que funciona como necessário, você é melhor fora de usar que (ver os outros posts). Se houver outros desenvolvedores no mesmo código, eles não precisam considerar se as obras padrão.

Não seria um trabalho simples declaração lock(Object)? Nos bastidores, ele cria o Monitor e seção crítica dentro de um bloco try... finally.

private static readonly Object lockMe = new Object();
lock(lockMe)
{
    // critical code
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top