Programação multithread exige muitas vezes que o programador implemente seu próprio código para garantir sincronização e thread segura. Muitas vezes esquecemos que num ambiente multi thread, threads distintas podem estar acessando informações de maneira incorreta.

Vejamos no exemplo a seguir um código multi thread sem a utilização de mecanismo de sincronização.

Não podemos garantir o output desse código uma vez que não temos nenhum mecanismo de sincronização entre threads. O output desse código seria algo parecido com isso:

0134567892

Para garantir sincronização entre as threads, necessitamos adicionar um semáforo. Neste caso utilizaremos o Lock. Neste primeiro exemplo vamos utilizar o lock de uma maneira incorreta para entao entendermos porque esta utilização não é à adequada.

Abaixo mesmo código, agora com o lock:

Com essa alteração garantimos que 100% das vezes o código executado terá o seguinte output:

0123456789

Você deve estar se perguntando o que esta errado na utilização do Lock(this) ?

Quando você utiliza lock(this), a visibilidade do objeto locado é a mesma que a visibilidade da classe, neste caso se sua classe é publica, o objeto locado esta visivel em qualquer lugar. Isso torna possivel a introdução de um deadlock na sua classe por qualquer parte do código, tornando muito dificil o diagnóstico do deadlock.

Solucionar o problema é muito facil. Basta adicionar um objeto de sincronização privado e utilizarmos este no nosso lock como mostrado abaixo:

Lembrete:

  • lock(this) é um problema se a instância pode ser acessada publicamente.
  • lock(typeof (MyType)) é um problema se MyType é acessado publicamente.
  • lock(“myLock”) é um problema se qualquer outro código no mesmo processo estiver usando a mesma string.

Melhor prática é definir um objeto privado de sincronização ou um objeto estático privado para proteger dados comun entre todas as instancias.

Espero que essa dica seja útil,

Um grande abraço.