Aviso sobre alguns cuidados com as threads

Trabalhar com threads parece bem simples, huh? Realmebte é! Mas você tem que considerar algumas coisas relacionadas ao sincronismo que tentei explicar no último post.

Uma thread pura é aquela que não exige mecanismos de sincronia, ou seja, não tenta usar objetos globais ou compartilhados. Quanto mais pura você deixar sua função que será paralelizada, melhor. Nem sempre isso é possível. Especialmente porque existem funções da libc e de outras bibliotecas que não são thread safe.

Thread safety é o conceito de que uma função precisa ser reentrante, ou seja, todos os recursos que uma thread usa devem estar contidos no contexto da thread. Variáveis globais não estão contidas no contexto das threads secundárias (estão na thread primária!) e, por isso, ao usar essas variáveis você precisa de mecanismos de sincronia. Algumas funções também usam variáveis globais ou recursos “globais” (do ponto de vista da função) do sistema operacional. O exemplo do post anterior tem um problema em potencial: As threads secundárias usam a função printf, que não é thread safe.

A função printf usa um descritor global chamado stdout, que é comum ao processo inteiro. Assim, multiplas chamadas simultâneas à printf pode gerar problemas. Deixei o exemplo como está porque minha intenção era usar o printf como ferramenta de debug apenas, mas a maneira correta seria colocá-lo dentro da trava dos mutexes.

Consulte a manpage pthreads para ver uma listagem de funções da libc que não thread safe.

Além da libc, por exemplo, a biblioteca OpenGL não é thread safe. O motivo é o mesmo: As matrizes de transformação e os vários estados mantidos pela biblioteca são globais. Tenha cuidado ao usar funções de terceiros com threads.

Outro problema que pode surgir são os deadlocks (“travas da morte?!”). Em essência, se um mutex é travado e jamais “destravado” as outras threads que o usam jamais serão executadas na totalidade. As demais threads que o usam ficarão suspensas eternamente, parecendo mortas (“dead locked”). Aliás, esse é um jeito de iniciar threads em modo suspenso: Inicialize  e trave um mutex na thread principal e o use nas threads criadas com pthread_create. Essas threads secundárias serão suspensas na primeira tentativa de chamar pthread_mutex_lock, ficando suspensas até a thread principal chamar pthread_mutex_unlock. Lembre-se que a biblioteca pthreads não permite criação de threads suspensas por default (ao contrário da função CreateThread, no Windows).

É isso… :)

Anúncios

Deixe um comentário

Faça o login usando um destes métodos para comentar:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair / Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair / Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair / Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair / Alterar )

Conectando a %s