Vejo que, ao usar objetos que não são seguros para threads, envolvemos o código com um bloqueio como este:
private static readonly Object obj = new Object();
lock (obj)
{
// thread unsafe code
}
Então, o que acontece quando vários threads acessam o mesmo código (vamos supor que ele esteja sendo executado em um aplicativo Web ASP.NET). Eles estão na fila? Se sim, quanto tempo eles vão esperar?
Qual é o impacto no desempenho devido ao uso de bloqueios?
Respostas:
A
lock
declaração é traduzida pelo C # 3.0 para o seguinte:No C # 4.0, isso foi alterado e agora é gerado da seguinte maneira:
Você pode encontrar mais informações sobre o que
Monitor.Enter
faz aqui . Para citar o MSDN:O
Monitor.Enter
método irá esperar infinitamente; ele vai não expirar.fonte
obj
sem que todo o sistema entre em conflito.lock
instrução e do Monitor: para que você possa executar uma operação em um encadeamento sem precisar se preocupar com outro encadeamento.É mais simples do que você pensa.
De acordo com a Microsoft : A
lock
palavra-chave garante que um segmento não entre em uma seção crítica do código enquanto outro segmento está na seção crítica. Se outro encadeamento tentar inserir um código bloqueado, ele aguardará, bloqueado, até que o objeto seja liberado.A
lock
palavra-chave chamaEnter
no início do bloco eExit
no final do bloco.lock
palavra-chave realmente lida com aMonitor
classe no back-end.Por exemplo:
No código acima, primeiro o thread entra em uma seção crítica e, em seguida, será bloqueado
obj
. Quando outro thread tenta entrar, ele também tenta bloquearobj
, que já está bloqueado pelo primeiro thread. O segundo thread precisará aguardar o lançamento do primeiro threadobj
. Quando o primeiro thread sair, outro será bloqueadoobj
e entrará na seção crítica.fonte
Não, eles não estão na fila, estão dormindo
Uma declaração de bloqueio do formulário
onde x é uma expressão de um tipo de referência, é precisamente equivalente a
Você só precisa saber que eles estão esperando um pelo outro, e apenas um segmento entrará para bloquear o bloco, os outros esperarão ...
O monitor está totalmente escrito em .net, por isso é rápido o suficiente, veja também a classe Monitor com refletor para obter mais detalhes
fonte
lock
instrução mudou ligeiramente em C # 4: blogs.msdn.com/b/ericlippert/archive/2009/03/06/…Bloqueios impedem que outros threads executem o código contido no bloco de bloqueio. As linhas terão que esperar até que a linha dentro do bloco de bloqueio seja concluída e a trava seja liberada. Isso tem um impacto negativo no desempenho em um ambiente multithread. Se você precisar fazer isso, verifique se o código no bloco de bloqueio pode processar muito rapidamente. Você deve tentar evitar atividades caras, como acessar um banco de dados, etc.
fonte
O impacto no desempenho depende da maneira como você bloqueia. Você pode encontrar uma boa lista de otimizações aqui: http://www.thinkingparallel.com/2007/07/31/10-ways-to-reduce-lock-contention-in-threaded-programs/
Basicamente, você deve tentar bloquear o mínimo possível, pois coloca seu código em espera no modo de suspensão. Se você tiver alguns cálculos pesados ou código duradouro (por exemplo, upload de arquivo) em um bloqueio, isso resultará em uma enorme perda de desempenho.
fonte
do { oldValue = thing; newValue = updated(oldValue); } while (CompareExchange(ref thing, newValue, oldValue) != oldValue
]. O maior perigo é que, se os requisitos evoluírem além do que essas técnicas podem lidar, pode ser difícil adaptar o código para lidar com isso.A parte na instrução lock pode ser executada apenas por um thread, portanto, todos os outros threads aguardarão indefinidamente que o thread que segura a trava termine. Isso pode resultar em um chamado deadlock.
fonte
A
lock
instrução é traduzida para chamadas para os métodosEnter
eExit
deMonitor
.A
lock
instrução aguardará indefinidamente o lançamento do objeto de bloqueio.fonte
O bloqueio está realmente oculto na classe Monitor .
fonte