Escrevendo um programa em Win32 multithread

Quando você escreve um programa com vários segmentos, você deve coordenar seu comportamento e usar os recursos do programa de. Você também deve certificar-se de que cada thread recebe sua própria pilha.

Compartilhamento de recursos comuns entre Threads

ObservaçãoObservação

Para obter uma discussão semelhante do ponto de vista do MFC, consulte Multithreading: Dicas de Programação e Multithreading: Quando usar as Classes de sincronização.

Cada segmento possui sua própria pilha e registra a sua própria cópia da CPU. Outros recursos, como, por exemplo, arquivos, dados estáticos e memória do heap, são compartilhados por todos os segmentos no processo. Usando esses recursos comuns de segmentos devem ser sincronizados. Win32 fornece várias maneiras para sincronizar os recursos, incluindo os semáforos, seções críticas, eventos e exclusões mútuas.

Quando vários segmentos estão acessando dados estáticos, o seu programa deve fornecer para conflitos de recursos possível. Considere a possibilidade de um programa no qual um thread atualiza a uma estrutura de dados estáticos que contém x,y coordenadas para os itens a serem exibidos por outro thread. Se o segmento de atualização altera o x coordenar e é superado antes que ele pode alterar o y coordenada, o thread de exibição pode ser agendado para antes do y coordenada é atualizada. O item será exibido no local errado. Você pode evitar esse problema usando semáforos para controlar o acesso à estrutura.

Um mutex (abreviação de mutual exconclusão) é uma forma de comunicação entre segmentos ou processos que estão em execução assíncrona uma da outra. Essa comunicação é normalmente usada para coordenar as atividades de vários segmentos ou processos, normalmente, controlando o acesso a um recurso compartilhado pelo bloqueio e desbloqueio do recurso. Para solucionar esse problema x,y problemas de atualizações coordenadas, o segmento de atualização define um mutex, indicando que a estrutura de dados está em uso antes de executar a atualização. O mutex seria claro depois de ambas as coordenadas tinham sido processadas. O thread de exibição deve aguardar o mutex ser honesto, antes de atualizar a exibição. Esse processo de aguardar um mutex geralmente é chamado de bloqueio em um mutex porque o processo é bloqueado e não pode continuar até que o mutex é limpa.

O programa Bounce.c mostrado na Programa de exemplo C Multithread usa um mutex chamado ScreenMutex para coordenar as atualizações de tela. Cada vez que um dos threads de exibição está pronto para escrever na tela, ele chama WaitForSingleObject com a alça para ScreenMutex e a constante infinito para indicar que o WaitForSingleObject chamada deve bloquear o mutex e não o tempo limite. Se ScreenMutex estiver desmarcada, a função espera define o mutex para que outros threads não possam interferir com a exibição e continua a execução da thread. Caso contrário, o thread bloqueia até que o mutex é limpa. Quando o segmento concluir a atualização de vídeo, ele libera o mutex chamando ReleaseMutex.

Exibe a tela e dados estáticos são apenas dois dos recursos que exigem gerenciamento cuidadoso. Por exemplo, o seu programa pode ter vários segmentos acessando o mesmo arquivo. Porque outro thread pode ter sido movido o ponteiro de arquivo, cada thread deve redefinir o ponteiro do arquivo antes de ler ou gravar. Além disso, cada thread deve certificar-se de que não é superado entre o momento em que ele posiciona o ponteiro e o tempo que ele acessa o arquivo. Esses segmentos devem usar um semáforo para coordenar o acesso ao arquivo cercando cada acesso de arquivo com WaitForSingleObject e ReleaseMutex chamadas. 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 espaço de pilha padrão do aplicativo é alocado para o primeiro thread de execução, o que é conhecido como o thread 1. Como resultado, você deve especificar a quantidade de memória para alocar, de uma pilha separada para cada segmento adicional, seu programa precisa. O sistema operacional aloca espaço de pilha adicionais para o segmento, se necessário, mas você deve especificar um valor padrão.

O primeiro argumento da _beginthread chamada é um ponteiro para o BounceProc função, que executa os threads. O segundo argumento especifica o tamanho de pilha padrão para o segmento. O último argumento é um número de identificação é passado para BounceProc. BounceProc usa o número de identificação para propagar o gerador de números aleatórios e para selecionar o atributo de cor do segmento e exibir o caractere.

Segmentos que fazem chamadas para a biblioteca de tempo de execução C, ou para a API do Win32 devem permitir que o espaço de pilha suficiente para a biblioteca e eles chamam funções da API. C printf função requer mais de 500 bytes de espaço de pilha, e você deve ter 2K de espaço de pilha disponível quando chamando rotinas de API do Win32.

Como cada segmento possui sua própria pilha, você pode evitar possíveis colisões sobre itens de dados, usando como poucos dados estáticos quanto possível. Seu programa para usar variáveis de pilha automática para todos os dados podem ser particulares de um segmento de design. As variáveis globais somente no programa de Bounce.c são mutexes ou variáveis que nunca é alterado depois que eles são inicializados.

Win32 também fornece o armazenamento Local de segmento (TLS) para armazenar dados por thread. For more information, see (TLS) de armazenamento Local de segmento..

Consulte também

Conceitos

Multithreading com c e Win32