Escrevendo um programa Win32 multithread
Quando você grava um programa com vários threads, é preciso coordenar seu comportamento e uso de recursos do programa. Você também deve ter certeza de que cada thread recebe seus próprios pilha.
Compartilhando recursos comuns entre os threads
Dica
Para obter uma discussão semelhante do ponto de vista de MFC, consulte Multithread: dicas de programação e Multithread: quando usar as classes de sincronização.
Cada thread tem sua própria pilha e sua própria cópia da CPU é registrada. Outros recursos, como arquivos, dados estáticos, e memória heap, são compartilhados por todos os threads no processo. Os threads que usam esses recursos comuns devem ser sincronizadas. O Win32 o fornece várias maneiras para sincronizar os recursos, incluindo dois semáforos, seções críticas, eventos, e mutexes.
Quando vários threads estão acessando dados estáticos, o programa deve prever conflitos possíveis de recursos. Considere um programa onde um thread atualiza uma estrutura de dados estático que contém as coordenadas x,y para os itens a serem exibidos por outro thread. Se o thread de atualização altera a coordenada x e é cancelado antes que seja possível modificar a coordenada y , o thread de exibição pode ser agendado antes que a coordenada y seja atualizada. O item será exibido no local errado. Você pode evitar este problema usando dois semáforos para controlar o acesso à estrutura.
Um mutex (curto para exclusão mútua) é uma maneira de comunicação entre threads ou processos que estão sendo executadas de forma assíncrona de outro. Essa comunicação normalmente é usada para coordenar as atividades de vários threads ou de processos, normalmente controlando o acesso a um recurso compartilhado bloqueando e desbloqueando o recurso. Para resolver esse problema, xde atualização da coordenaday , o thread de atualização um mutex que indica que a estrutura de dados estiver em uso antes de executar a atualização. Desmarcaria o mutex depois que ambas as coordenadas tivesse sido processadas. O thread de exibição deve aguardar o mutex para estar claro antes de atualizar a exibição. Esse processo de espera um mutex é geralmente chamado de bloqueio em um mutex como o processo está bloqueado e não pode continuar até que o mutex de seleção.
O programa de Bounce.c mostrado em Programa C multithread de exemplo usa um mutex nomeada ScreenMutex para coordenar atualizações da tela. Cada vez que um dos threads de vídeo estiver pronto para gravar na tela, chama WaitForSingleObject com o identificador para ScreenMutex e a INFINITE constante para indicar que a chamada de WaitForSingleObject deve bloqueio no mutex e não em tempo limite. Se ScreenMutex é claro, a função de espera define o mutex para que outros threads não podem interferir com a exibição e não continuam executando o thread. Caso contrário, o thread até o mutex a limpeza. Quando o thread termina a atualização de exibição, libera o mutex chamando ReleaseMutex.
As visualizações óticas e os dados são estáticos somente dois dos recursos que exigem o gerenciamento cuidado. Por exemplo, o programa pode ter vários threads que acessam o mesmo arquivo. Porque outro thread pode mover o ponteiro de arquivo, cada thread deve reiniciar o ponteiro de arquivo antes de ler ou gravar. Além disso, cada thread deve ter certeza de que não será cancelado entre a hora em que coloca o ponteiro e hora acessar o arquivo. Esses threads deve usar um sinal para coordenar acesso ao arquivo que cada acesso ao arquivo com chamadas de WaitForSingleObject e de ReleaseMutex . O exemplo de código a seguir ilustra essa técnica:
HANDLE hIOMutex= CreateMutex (NULL, FALSE, NULL);
WaitForSingleObject( hIOMutex, INFINITE );
fseek( fp, desired_position, 0L );
fwrite( data, sizeof( data ), 1, fp );
ReleaseMutex( hIOMutex);
Pilhas de thread
Todo o espaço padrão da pilha de um aplicativo é atribuído ao primeiro thread de execução, conhecida como o thread 1. No, você deve especificar a quantidade de memória a ser alocada para uma pilha separada para cada thread adicional o programa precisa. O sistema operacional atribuirá o espaço extra da pilha do thread se necessário, mas você deve especificar um valor padrão.
O primeiro argumento na chamada de _beginthread é um ponteiro para a função de BounceProc , que executa os threads. O segundo argumento especifica o tamanho padrão da pilha para o thread. O último argumento é um número de identificação que é passado a BounceProc. BounceProc usa o número de identificação para propagar o gerador de números aleatórios e selecione o caractere de atributo e a exibição da cor de thread.
Os threads que faz chamadas na biblioteca de tempo de execução C ou a API do Win32 devem permitir espaço suficiente da pilha para a biblioteca e as funções de API que chamam. A função C printf precisar de mais de 500 bytes de espaço da pilha, e você deve ter 2K de espaço de pilha suficiente disponível ao chamar rotinas da API do Win32.
Como cada thread tem sua própria pilha, você pode evitar colisões potenciais sobre itens de dados usando como alguns dados estáticos possível. Criar seu programa para usar variáveis automática da pilha para todos os dados que podem ser privados a um thread. Os únicos variáveis globais no programa de Bounce.c são mutexes ou variáveis que nunca se alteram depois que são inicializados.
O Win32 (TLS) também fornece o armazenamento de thread local para os dados do thread do repositório. Para obter mais informações, consulte Armazenamento local de thread (TLS).