Você está offline; aguardando reconexão

Não há suporte para seu navegador

Você precisa atualizar seu navegador para usar o site.

Atualize para a versão mais recente do Internet Explorer

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

IMPORTANTE: Este artigo foi traduzido pelo software de tradução automática da Microsoft e eventualmente pode ter sido editado pela Microsoft Community através da tecnologia Community Translation Framework (CTF) ou por um tradutor profissional. A Microsoft oferece artigos traduzidos automaticamente por software, por tradutores profissionais e editados pela comunidade para que você tenha acesso a todos os artigos de nossa Base de Conhecimento em diversos idiomas. No entanto, um artigo traduzido pode conter erros de vocabulário, sintaxe e/ou gramática. A Microsoft não é responsável por qualquer inexatidão, erro ou dano causado por qualquer tradução imprecisa do conteúdo ou por seu uso pelos nossos clientes.

Clique aqui para ver a versão em Inglês deste artigo: 317723
Sumário
Visual Basic .NET ou Visual Basic 2005 oferece a capacidade de usar threads em aplicativos Visual Basic pela primeira vez. Threads introduzem problemas de depuração, como condições de disputa 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 segundo thread lê o mesmo valor da variável. O encadeamento de primeiro e segundo thread executam suas operações no valor e participe de uma corrida para ver qual thread pode gravar o valor última variável compartilhada. O valor do segmento que grava o valor última será preservado, porque o thread está escrevendo sobre o valor que escreveu o segmento anterior.

Detalhes e exemplo

Cada segmento é alocado um período predefinido de tempo de execução em um processador. Quando expira o tempo alocado para o segmento, 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 uma linha de comando pode causar uma condição de corrida? Examine o exemplo a seguir para ver como uma condição de corrida ocorre. Há dois segmentos, e ambos estão 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				
Código de assembly (com números de linha) de compilação do código do 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 				
Examinando 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 de adição. Um segmento pode ser capaz de executar todo ou parte do seu código de assembly durante o tempo do processador. Agora veja como uma condição de concorrência ocorre deste código.

Total é 100, val1 é 50 e val2 é 15. O thread 1 obtém uma oportunidade de executar, mas apenas conclui as etapas 1 a 3. Isso significa que o Thread 1 ler a variável e concluir a adição. Segmento 1 agora é só esperando para gravar seu novo valor de 150. Depois que o Thread 1 for interrompido, o Thread 2 obtém seja completamente executada. Isso significa que ele escreveu o valor que ela calculada (85)-out ao Total da variável. Finalmente, o Thread 1 recupera o controle e finaliza a execução. Ele grava seu valor (150). Portanto, quando o 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 fosse um programa bancário, o cliente tem dinheiro em sua conta não deve estar presente.

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

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. Faça isso com moderação, pois se uma variável está bloqueada no Thread 1 e Thread 2 também precisa da variável, a execução do Thread 2 pára enquanto o Thread 2 aguarda 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 compartilhados entre vários threads. Isso é resultado da imprevisibilidade da ordem na qual os threads de execução. Um dia wins de um thread e um dia o outro wins thread. Em outros momentos, a execução funciona corretamente. Além disso, se cada thread é executada separadamente, o valor da variável funciona corretamente.

Travamentos

Um deadlock ocorre quando dois threads cada bloquear uma variável diferente ao mesmo tempo e, em seguida, tentam bloquear a variável que outro thread já está bloqueado. Como resultado, cada thread interromperá a execução e aguarda o segmento liberar a variável. Como cada thread está mantendo a variável que deseja que o outro thread, não acontece nada, e os segmentos permanecem bloqueados.

Detalhes e exemplo

O código a seguir possui dois objetos, LeftVal e RightVal:
'Thread 1SyncLock LeftVal SyncLock RightVal  'Perform operations on LeftVal and RightVal that require read and write. End SyncLockEnd SyncLock				
'Thread 2SyncLock RightVal SyncLock LeftVal  'Perform operations on RightVal and LeftVal that require read and write. End SyncLockEnd SyncLock				
Um deadlock ocorre quando o Thread 1 é permitido para bloquear LeftVal. O processador interrompe a execução do Thread 1 e começa a execução do Thread 2. Thread 2 bloqueios RightVal e, em seguida, tenta bloquear LeftVal. Porque LeftVal está bloqueado, o Thread 2 pára e aguarda LeftVal a ser liberado. Porque o Thread 2 for interrompido, o Thread 1 é permitido continue em execução. O thread 1 tenta bloquear RightVal mas não, porque o Thread 2 bloqueou. Como resultado, o Thread 1 começa a aguardar RightVal torna-se 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 está mantendo.

Um deadlock não ocorra. Se o Thread 1 executa os dois bloqueios antes que o processador para ele, Thread 1 pode executar suas operações e, em seguida, desbloquear variável compartilhada. Após o Thread 1 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 poderá aparecer em módulos separados ou áreas do seu código. Este um erro muito difícil rastrear porque, desse mesmo código, execução correta e execução incorreta podem ocorrer.

Sintomas

Um sintoma comum de bloqueio é que o programa ou grupo de threads pára de responder. Isso também é conhecido como um travamento. Pelo menos dois segmentos estão esperando uma variável que outro thread bloqueado. Os segmentos não continuar, pois nenhum thread irá lançar sua variável até que ele chegue a outra variável. O programa pode travar 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 sim de 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 segmento. Um único processo pode conter vários threads de execução. Cada segmento mantém seus próprios manipuladores de exceção, agendamento de prioridades e um conjunto de estruturas que o sistema operacional usa para salvar o contexto do thread se o thread não pode concluir sua execução durante o tempo em que ele foi atribuído ao processador. O contexto é mantido até a próxima vez que o thread recebe a tempo do processador. O contexto inclui todas as informações que o segmento requer perfeitamente continuar sua execução. Essas informações incluem o conjunto do segmento de registradores do processador e a pilha de chamadas dentro do espaço de endereço do processo do host.
Referências
Para obter mais informações, pesquise na Ajuda do Visual Studio para as seguintes palavras-chave:
  • SyncLock. Permite que um objeto seja bloqueado. Se outro thread tenta bloquear o mesmo objeto, ele será bloqueado até que o primeiro thread libera. Use SyncLock com cuidado, pois pode haver problemas contra o uso indevido do SyncLock. Por exemplo, este comando pode evitar condições de corrida, mas causar deadlocks.
  • Sincronização. 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 Microsoft:
316422 INFO: Roteiro para Threading no Visual Basic .NET
Para obter mais informações, consulte o seguinte site da MSDN:

Aviso: este artigo foi traduzido automaticamente

Propriedades

ID do Artigo: 317723 - Última Revisão: 10/29/2013 01:30:00 - Revisão: 3.0

  • Microsoft Visual Basic 2005
  • Microsoft Visual Basic .NET 2003 Standard Edition
  • Microsoft Visual Basic .NET 2002 Standard Edition
  • kbvs2005swept kbvs2005applies kbinfo kbmt KB317723 KbMtpt
Comentários
s://c1.microsoft.com/c.gif?DI=4050&did=1&t=">did=1&t=">ld(m);" onload="var m=document.createElement('meta');m.name='ms.dqp0';m.content='false';document.getElementsByTagName('head')[0].appendChild(m);" src="http://c1.microsoft.com/c.gif?"> >did=1&t="> + "//c.microsoft.com/ms.js'><\/script>"); >