questão C # multithreading com o Monitor de classe - possível lifelock?
-
22-07-2019 - |
Pergunta
Eu tenho um pouco de código, que eu não consigo descobrir corretamente. O problema é que o programa é multithreaded e dentro há um pouco de código que devem ser sincronizados então eu escrevi o seguinte:
lock (lockObject)
{
if (!Monitor.TryEnter(lockObject))
Monitor.Wait(lockObject);
//do stuff...
Monitor.PulseAll(lockObject);
}
Monitor.Exit(lockObject);
o problema que eu tenho é que em algum ponto no tempo os tópicos parecem estar dormindo - alguém pode dizer por quê? O programa continua a funcionar junto indefinidamente consome quase nenhum cpu, mas nenhum trabalho é feito - quando o rastreamento do programa que eu descobri que em algum ponto sem fio está ativa, mas um monte deles está dormindo. Eu sei que o erro maior parte (no caso de um desenvolvedor - sempre) fica 0.5m na frente do monitor -, mas não consigo descobrir sozinho ... talvez em poucos minutos;)
Alguém pode explicar isso para mim -. Obrigado antecipadamente
Solução
Existe uma diferença entre LockObject
e lockObject
? Não está claro ...
No entanto! Se eles são diferentes objetos, em seguida, em primeiro lugar: você não pode Wait
em um bloqueio que você não tem ... e TryEnter
só retornará false se você especificar um tempo limite. O que exatamente é que o código está tentando fazer?
Sem mais contexto, não está totalmente claro o que o PulseAll
e Wait
são projetados para fazer; por exemplo, aqui eles são usados ??para bloquear a fila quando é muito cheio (Wait
), ou liberá-lo quando o espaço se torna disponível (PulseAll
), etc. é difícil depurar o código rosca sem as interações completas entre threads.
Parece que você só precisa:
lock (lockObject)
{
// do stuff
}
Existem dois problemas imediatos que eu posso ver; em primeiro lugar, não é óbvio que você sempre liberar os bloqueios que você toma (ou seja, exceções). Tente lock
uso apenas para o Enter/Exit
-. Ele vai acertar
Em segundo lugar; se todo o Wait
tópicos chamada ... quem vai acordá-los? O que eles estão esperando ? Conforme apresentado:. Sim, todos eles vão dormir indefinidamente
Outras dicas
Estou assming a primeira declaração de bloqueio é um erro de digitação e você significou bloqueio (LockObject) (em minúsculas).
Eu acho que você está mal-entendido bloqueia um pouco aqui. O bloco se em seu código nunca vai ser verdade. A razão é que lock (LockObject) realmente exapands para o seguinte
Monitor.Enter(lockObject);
try {
...
} finally{
Monitor.Exit(lockObject);
Assim, quando você acertar o bloco if você já possui o bloqueio e TryEnter deve sempre ter sucesso.
Essa é uma configuração estranha. 'LockObject' é o mesmo que 'LockObject'? Ou isso é um erro de digitação? Se eles são o mesmo, então a sua configuração é redundante, já que não há necessidade de chamar Monitor.TryEnter em algo que você já está travando. Se 'LockObject' é um objeto diferente, então por que não mover o Monitor.Exit para dentro da declaração de bloqueio?