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:
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.