O que é uma condição racial?

Ao escrever aplicações multi-tarefas, um dos problemas mais comuns encontrados são as condições raciais.

As minhas perguntas para a comunidade são:

O que é uma condição racial? Como é que os detecta? Como você lida com eles? Finalmente, como você evita que elas ocorram?

Solução

Uma condição racial ocorre quando dois ou mais tópicos podem acessar dados compartilhados e eles tentam mudá-los ao mesmo tempo. Como o algoritmo de agendamento de threads pode trocar entre threads a qualquer momento, você não sabe a ordem em que os threads tentarão acessar os dados compartilhados. Portanto, o resultado da mudança nos dados depende do algoritmo de programação de threads, ou seja, ambas as threads estão "em corrida" para acessar/alterar os dados.

Frequentemente ocorrem problemas quando um thread faz um "check-then-act" (por exemplo, "check" se o valor é X, então "act" para fazer algo que depende do valor ser X) e outro thread faz algo para o valor entre o "check" e o "act". Por exemplo, "check":

if (x == 5) // The "Check"
{
   y = x * 2; // The "Act"

   // If another thread changed x in between "if (x == 5)" and "y = x * 2" above,
   // y will not be equal to 10.
}

O ponto sendo, y pode ser 10, ou pode ser qualquer coisa, dependendo se outro fio mudou x entre a verificação e o ato. Você não tem uma maneira real de saber.

A fim de evitar a ocorrência de condições de corrida, você normalmente colocaria um cadeado em torno dos dados compartilhados para garantir que apenas um tópico possa acessar os dados de cada vez. Isto significaria algo como isto:

// Obtain lock for x
if (x == 5)
{
   y = x * 2; // Now, nothing can change x until the lock is released. 
              // Therefore y = 10
}
// release lock for x
Comentários (18)

Uma condição racial é um tipo de bug, que acontece apenas com certas condições temporais.

Exemplo: Imagine que você tem dois fios, A e B.

Na linha A:

if( object.a != 0 )
    object.avg = total / object.a

Na linha B:

object.a = 0

Se a thread A for preemptada logo após ter verificado que o object.a não é nulo, B fará a = 0, e quando a thread A ganhar o processador, ele fará uma "divisão por zero".

Este bug só acontece quando o thread A é preemptado logo após a declaração do if, é muito raro, mas pode acontecer.

Comentários (0)

Uma condição de corrida é uma situação em programação concorrente onde dois fios ou processos concorrentes competem por um recurso e o estado final resultante depende de quem obtém o recurso primeiro.

Comentários (3)