Cuattre-Equilibrar-Pratos-Personas
Share on facebook
Share on twitter
Share on linkedin

Como utilizar o ThreadStaticAttribute

Algumas vezes, no desenvolvimento multi-thread, queremos acessar alguma informação ou utilizar algum campo que possuirá valores diferentes para cada Thread da aplicação. Para esses casos podemos utilizar o ThreadStaticAttribute.

Quando marcamos uma variável como ThreadStatic, basicamente, estamos dizendo que cada thread que a utilizar terá sua própria cópia da variável. Dessa forma, ainda que várias threads referenciem a mesma variável, cada thread pode atribuir valores distintos para a variável sem o risco de que este seja sobrescrito ou acessado por threads diferentes. Isso, inclusive, garante de forma bem simples que essa implementação seja thread-safe [1].

Com o ThreadStatic é possível compartilhar uma variável estática entre diferentes classes e métodos em um segmento e ainda encapsulá-lo, “escondendo-o” de outras threads. Isso faz da variável ThreadStatic mais isolada que uma variável estática normal, sendo especialmente útil quando, em uma aplicação multi-thread, não se deseja passar um objeto como parâmetro entre várias classes, métodos e camadas diferentes da aplicação.

O ThreadStatic é comumente utilizado como mecanismo de cache e na gestão de transações em banco de dados. Nesta última, é recorrente a necessidade de se passar o objeto da transação entre diferentes chamadas de métodos, que por sua vez estão distribuídas em classes distintas. Utilizando uma variável estática marcada como ThreadStatic para referenciar a transação atual você elimina a necessidade de passar o objeto da transação como parâmetro por todos os métodos que for utilizar [2].

Outro exemplo interessante de uso do ThreadStaticAttribute é em uma comunicação cliente-servidor via socket. O servidor executa uma thread para cada socket de conexão, dessa forma é possível utilizar o ThreadStatic para armazenar informações do socket cliente ou outras informações referentes a conexão garantindo que não haverá interferência nas informações entre Threads diferentes.

É importante lembrar, contudo, que o ThreadStaticAttribute não é uma “solução mágica e infalível”. Para que ele cumpra seu papel de “facilitador” no desenvolvimento multi-thread é imprescindível que se conheça as formas corretas de utilizar esse recurso, as situações em que ele se torna uma opção interessante ao desenvolvimento e, ainda mais, as situações onde seu uso não é recomendado.

De início temos que a marcação de ThreadStatic só pode ser utilizada em variáveis estáticas (static) [3]. Se tentarmos utilizá-la em uma variável que não seja estática a marcação será ignorada e o comportamento dela não corresponderá ao esperado.

                                         [ThreadStatic]
private static string variavel;

 

Outro cuidado que devemos ter é o de evitar “inicializar” uma variável ThreadStatic. Isso porque essa “inicialização” ocorrerá apenas uma vez e impactará apenas a thread corrente. Para as demais threads que venham a utilizar a variável ela terá valor nulo (null). Isso não significa, porém, que não há formas de contornar essa situação caso seja necessário atribuir um valor padrão ou inicial à variável. Uma forma simples de resolver essa questão é utilizar uma propriedade estática para retornar a variável ThreadStatic quando essa já estiver preenchida, ou o valor padrão quando ela estiver nula.

                         [ThreadStatic]
                         private static string _variavel;
public static string Variavel { get { return _foo ?? "TEST"; } }

Por fim, mas de grande importância, ao se utilizar o ThreadStaticAttribute é fundamental conhecer bem o ciclo de vida das threads, para garantir que o valor da variável não está sendo alterado indevidamente em algum ponto da aplicação, ocasionando erros inesperados. Se as threads podem ser reutilizadas ou encerradas sem seu controle direto ou se a aplicação pode rodar em threads diferentes ao longo de seu ciclo de vida, por exemplo, é importante ter cuidado redobrado para que a variável não seja alterada de maneira não intencional. Isso significa que não se deve, de forma alguma, utilizar o ThreadStaticAttribute em aplicações que utilizem ThreadPool ou ASP.Net por exemplo? Não! É possível utilizá-lo sim, mas com cautela, sempre atento aos possíveis casos de erro e realizando testes confiáveis e completos o suficiente para garantir que a aplicação está funcionando corretamente [4].

O ThreadStaticAttribute é uma boa ferramenta, mas, como toda ferramenta, é preciso conhecê-la bem e dominar seus pontos fortes e fracos para que ela atenda às necessidades do desenvolvimento. Sabendo usá-la e estando atento aos seus impactos, ela oferece uma solução simples e eficiente para vários problemas e necessidades que podem surgir ao longo do desenvolvimento multi-thread. Por outro lado, usá-la de maneira indevida e displicente pode, além de não solucionar os problemas correntes da aplicação, criar novos erros e pontos de mal funcionamento.

Tem alguma dúvida sobre ThreadStaticAttribute? Entre em contato com a gente!

_______________

[1] Diz-se que uma aplicação é Thread-safe quando esta, ao trabalhar com estruturas de dados compartilhadas, garante que em um ambiente com várias threads rodando simultaneamente a informação é manipulada de forma segura, sem que a execução de uma thread ocasione um comportamento inesperado em outra thread.
[2] A gestão de transações pode ser realizada de maneira alternativa com a utilização do TransactionScope, mas por sua vez, o que o TransactionScope faz é, justamente, manter uma referência ThreadStatic para a transação atual.
[3] No .NET 4.0 é possível utilizar o “ThreadLocal”, que tem comportamento similar ao do ThreadStaticAttribute, mas com o diferencial de não exigir sua utilização em uma variável estática.
[4] Essa dica final, ou “regra”, vale para qualquer aplicação que você desenvolva, independente dos riscos e complexidade. Testar bem suas aplicações e garantir sua qualidade deve ser princípio básico de qualquer desenvolvedor.
Por: Matheus Miranda e Jéssica Saliba
Créditos da imagem: Cuattre Produções