Descrição das condições de corrida e deadlocks

ID do artigo: 317723 - Exibir os produtos aos quais esse artigo se aplica.
Expandir tudo | Recolher tudo

Nesta página

Sumário

Visual Basic .NET ou Visual Basic 2005 oferece a capacidade de usar threads em aplicativos Visual Basic pela primeira vez. Segmentos apresentam problemas de depuração como condições de corrida e deadlocks. Este artigo explora esses dois problemas.

Mais Informações

Condições de corrida

Uma condição de corrida ocorre quando dois threads acessem uma variável compartilhada ao mesmo tempo. O primeiro thread lê a variável, e o thread de segundo lê o mesmo valor da variável. Em seguida, o thread primeiro e segundo thread executar suas operações no valor e eles corrida para ver qual thread pode gravar o valor última variável compartilhada. O valor do thread que grava o valor última é preservado, porque o thread está escrevendo sobre o valor que escreveu o segmento anterior.

Exemplo e detalhes

Cada thread é alocada de um período de tempo para executar em um processador predefinido. Quando o tempo que está alocado para o segmento expira, o contexto do thread é salvo até a próxima vez no processador e o processador começa a execução do próximo segmento.

Como um comando de uma linha pode causar uma condição de corrida? Examine o exemplo a seguir para ver como uma condição de corrida ocorre. Há dois threads, e ambos estiverem atualizando uma variável compartilhada chamada total (que é representado como dword ptr ds: [031B49DCh] no código de assembly).

Código do Visual Basic:
   'Thread 1
   Total = Total + val1
				
   'Thread 2
   Total = Total - val2
				
o código de assembly (com números de linha) da compilação do código Visual Basic anterior:
 'Thread 1
 1.   mov         eax,dword ptr ds:[031B49DCh] 
 2.   add         eax,edi 
 3.   jno         00000033 
 4.   xor         ecx,ecx 
 5.   call        7611097F 
 6.   mov         dword ptr ds:[031B49DCh],eax 
				
 'Thread 2
 1.   mov         eax,dword ptr ds:[031B49DCh] 
 2.   sub         eax,edi 
 3.   jno         00000033 
 4.   xor         ecx,ecx 
 5.   call        76110BE7 
 6.   mov         dword ptr ds:[031B49DCh],eax 
				
por observando o código de assembly, você pode ver quantas operações o processador está executando no nível inferior para executar um cálculo simples adição. Um segmento não poderá executar todo ou parte do seu código de assembly durante seu tempo no processador. Agora, veja como uma condição de corrida ocorre desse código.

Total é 100, val1 é 50 e val2 é 15. O thread 1 obtém uma oportunidade para executar, mas somente conclui as etapas de 1 a 3. Isso significa que o thread 1 ler a variável e concluída a adição. Segmento 1 agora é só esperando para gravar o novo valor de 150. Depois thread 1 for interrompido, o thread 2 obtém para executar completamente. Isso significa que ele escreveu o valor que ela calculada (85) saída para o total de variável. Finalmente, o thread 1 recupera o controle e terminar a execução. Ele escreve seu valor (150). Portanto, quando thread 1 for concluído, o valor do total agora é 150 em vez de 85.

Você pode ver como isso pode ser um grande problema. Se isso fosse um programa bancário, o cliente teria dinheiro em sua conta não deve estar presente.

Este erro é aleatório, porque é possível para o thread 1 concluir sua execução antes de seu tempo no processador expira e, em seguida, o thread 2 pode começar sua execução. Se esses eventos ocorrem, o problema não ocorre. Execução de thread é não determinístico, portanto você não pode controlar o tempo ou ordem de execução. Observe também que os threads podem executar diferente em tempo de execução versus o modo de depuração. Além disso, você pode ver que se você executar cada thread na série, o erro não ocorrerá. Este aleatoriedade torna muito mais difícil rastrear e depurar esses erros.

Para evitar que as condições de corrida ocorra, você pode bloquear variáveis compartilhadas, para que apenas um thread por vez tenha acesso à variável compartilhada. Para fazer isso com moderação, pois se uma variável está bloqueada no thread 1 e thread 2 também precisa a variável, a execução do thread 2 pára enquanto aguarda thread 2 para o thread 1 liberar a variável. (Para obter mais informações, consulte "SyncLock" na seção "Referências" deste artigo.)

Sintomas

O sintoma mais comum de uma condição de corrida é imprevisíveis valores de variáveis que são compartilhadas entre vários threads. Isso resulta de imprevisibilidade da ordem na qual os threads executar. Wins de um thread de um dia e um dia outros wins de thread. Em outros momentos, execução funciona corretamente. Além disso, se cada thread é executada separadamente, o valor da variável funciona corretamente.

Deadlocks

Um deadlock ocorre quando dois threads cada bloqueio uma variável diferente ao mesmo tempo e, em seguida, tenta bloquear a variável que outro thread já está bloqueado. Como resultado, cada thread pára de executar e aguarda o outro segmento liberar a variável. Como cada thread está mantendo a variável que deseja que o outro thread, nada ocorre, e os segmentos permanecem deadlocked.

Exemplo e detalhes

O código a seguir possui dois objetos, LeftVal e RightVal:
'Thread 1
SyncLock LeftVal
 SyncLock RightVal
  'Perform operations on LeftVal and RightVal that require read and write.
 End SyncLock
End SyncLock
				
'Thread 2
SyncLock RightVal
 SyncLock LeftVal
  'Perform operations on RightVal and LeftVal that require read and write.
 End SyncLock
End SyncLock
				
um deadlock ocorre quando o thread 1 tem permissão para bloquear LeftVal. O processador pára o execução da thread 1 e começa a execução de thread 2. O thread 2 bloqueios RightVal e, em seguida, tenta bloquear LeftVal. Porque LeftVal está bloqueado, thread 2 pára e aguarda LeftVal a serem lançados. Porque o thread 2 for interrompido, thread 1 é permitida para continuar a execução. O thread 1 tenta bloquear RightVal mas não é possível, porque o thread 2 o bloqueou. Como resultado, o thread 1 começa a aguardar RightVal fica disponível. Cada segmento espera por outro thread, porque cada thread bloqueou a variável que outro thread está aguardando e nenhum thread é desbloquear a variável que está mantendo.

Um deadlock sempre não ocorre. Se o thread 1 executa os dois bloqueios antes do processador interrompe, thread 1 pode executar suas operações e, em seguida, desbloquear variável compartilhada. Após 1 thread desbloqueia a variável, thread 2 pode prosseguir com sua execução, conforme o esperado.

Este erro parece óbvio quando esses trechos de código são colocados lado a lado, mas na prática, o código pode aparecer em módulos separados ou áreas de seu código. Esse um erro muito difícil rastrear porque, do código mesmo, tanto execução correta execução incorreta podem ocorrer.

Sintomas

Um sintoma comum de deadlock é que o programa ou grupo de threads pára de responder. É também conhecido como uma paralisação . Pelo menos dois threads são cada uma variável que outro thread bloqueado aguardando. Os segmentos não continue, porque nenhum thread irá lançar sua variável até que ele obtém a outra variável. O programa inteiro pode paralisar se o programa está aguardando um ou ambos os threads para execução completa.

O que é um thread?

Processos são usados para separar os diferentes aplicativos que estão em execução em um horário especificado em um único computador. O sistema operacional não executa processos, mas fazer threads. Um segmento é uma unidade de execução. O sistema operacional aloca tempo do processador para um segmento para a execução de tarefas do thread. Um único processo pode conter vários threads de execução. Cada thread mantém seus próprio manipuladores de exceção, prioridades e um conjunto de estruturas que o sistema operacional usa para salvar o contexto do thread, se o thread não é possível concluir sua execução durante o tempo em que foi atribuída para o processador de agendamento. O contexto é mantido até a próxima vez que o thread recebe o tempo do processador. O contexto inclui todas as informações que o thread requer para perfeitamente continuar sua execução. Essas informações incluem conjunto do segmento de registradores do processador e a pilha de chamada dentro o espaço de endereço do processo de host.

Referências

Para obter mais informações, procure Ajuda do Visual Studio para as seguintes palavras-chave:
  • SyncLock . Permite que um objeto a ser bloqueada. Se outro thread tenta bloquear esse mesmo objeto, ele será bloqueado até que o primeiro thread libera. Use SyncLock cuidadosamente, pois podem ocorrer problemas contra uso indevido de SyncLock. Por exemplo, este comando pode evitar condições de corrida, mas causar deadlocks.
  • sincronizadas . Permite que um conjunto selecionado de thread-safe operações básicas variáveis numéricas.
Para obter informações adicionais, clique no número abaixo para ler o artigo na Base de dados de Conhecimento da Microsoft:
316422INFO: Guia para Threading no Visual Basic .NET
Para obter mais informações, consulte o seguinte site da MSDN:
Threads and Threading

Propriedades

ID do artigo: 317723 - Última revisão: quarta-feira, 6 de dezembro de 2006 - Revisão: 2.3
A informação contida neste artigo aplica-se a:
  • Microsoft Visual Basic 2005
  • Microsoft Visual Basic .NET 2003 Standard Edition
  • Microsoft Visual Basic .NET 2002 Standard Edition
Palavras-chave: 
kbmt kbvs2005swept kbvs2005applies kbinfo KB317723 KbMtpt
Tradução automática
IMPORTANTE: Este artigo foi traduzido por um sistema de tradução automática (também designado por Machine Translation ou MT), não tendo sido portanto traduzido ou revisto por pessoas. A Microsoft possui artigos traduzidos por aplicações (MT) e artigos traduzidos por tradutores profissionais, com o objetivo de oferecer em português a totalidade dos artigos existentes na base de dados de suporte. No entanto, a tradução automática não é sempre perfeita, podendo conter erros de vocabulário, sintaxe ou gramática. A Microsoft não é responsável por incoerências, erros ou prejuízos ocorridos em decorrência da utilização dos artigos MT por parte dos nossos clientes. A Microsoft realiza atualizações freqüentes ao software de tradução automática (MT). Obrigado.
Clique aqui para ver a versão em Inglês deste artigo: 317723

Submeter comentários