quarta-feira, 20 de fevereiro de 2008

C# e .NET - Thread Lock - Trancando recursos para execução de threads

Esse texto pode ser melhor visualizado na pagina da Inteligência Digital.

Para acessa-lo, basta clicar aqui.

As vezes é necessario que suas Threads acessem o mesmo objetos e modifiquem valores nesses objetos.
Porém se você estiver trabalhando com um computador multi-processado, por vezes os resultados serão erradospois uma thread vai desfazer o que a outra já fez.

Vou explicar melhor essa historia.

Exemplo Classico:
Temos um contador numa classe X

int contador = 0;

Só existe uma instancia da classe X no seu programa, e toda vez que suas threads fizerem determinada atividade,elas deve incrementar em 1 esse contador.

Nada mais normal do que a classe X possuir um metodo

public void AtualizaContador(){
contador++;
}

Para esse simples exemplo não estamos levando em conta as boas praticas e questões de encapsulamentoque são muito importantes também.

Agora num ambiente multi-processado, imagine 2 Threads no mesmo momento tentando fazer a atualização do contador.

Suponto que nesse ponto o contador tenha o valor 10
De maneira generica, para fazer a atualização, os passos dados pelo processador seriam:

- Salvar o valor 10 no registrador do processador
- Incrementar o valor contido no registrador em 1
- retornar o valor para memoria

Voltando ao exemplo...
Se duas Threads pegassem ao mesmo tempo o valor 10
as duas iam incrementar o valor para 11
porem na hora de salvar em memoria, uma delas ia salvar primeiro o valor 11
por consequencia a outra deveria salvar o valor 12 mas isso não acontece,
ela salva o valor 11 novamente por cima do valor 11 que já estava lá

Causando uma inconsistencia nos dados da nossa aplicação.
Temos diversas formas de tratar isso, principalmente porque incrementação é uma operação thread safe,então temos classes e metodos para tratar especificamente dessa situação.

Mas vamos tratar aqui como se fosse uma situação generica.
Dessa forma usaremos o lock do C#
De maneira muito simples de usar, o lock irá bloquear os recursos do objeto até que a thread que está utilizando o trecho do codigo acabe de processa-lo

Teriamos então o seguinte codigo:

public void AtualizaContador(){

lock(this){
contador++;
}
}

o lock recebe como parametro o this que é uma palavra reservada do C# que referencia o objeto em questão.
No caso, como o metodo está dentro da classe X o this então, representa a classe X
É como se a propria classe estivesse se referenciando.

Espero ter conseguido passar um pouco da importancia do lock.
Existem outras formas de fazer isso, mas teriamos que entrar em outras discussões como dead lock e etc...
então trarei isso em um outro post.
Talvez vocês não enxerguem a importancia disso num exemplo simples como esse, mas em ambientes complexos isso toma proporções enormes.

Espero ter ajudado
Até a proxima.

Esse texto pode ser melhor visualizado na pagina da Inteligência Digital.

Para acessa-lo, basta clicar aqui.

3 comentários:

Unknown disse...

Beleza João! Bom artigo fera!
Exatamente o que estava procurando.
Obrigado!

Anônimo disse...

Ótimo post João Bosco! Obrigado pela ajuda :)

Unknown disse...

Olá amigo. Não sei se é o mesmo que eu quero fazer.
Mas eu queria parar um método que eu tenho em um determinado ponto, até que eu entre com um valor vindo de uma página aspx e leve esse valor ao método.
Teria como fazer isso? Com esse lock por exemplo ou com outra forma?

 
João Bosco Seixas