Compartilhar via


Multithreading: Como usar as Classes de sincronização

Sincronizar acesso a recursos entre threads é um problema comum ao escrever aplicativos multissegmentados.Ter dois ou mais threads simultaneamente acesso que os mesmos dados podem levar a resultados imprevisíveis e indesejáveis.Por exemplo, um thread pode estar atualizando o conteúdo de uma estrutura enquanto outro thread está lendo o conteúdo da mesma estrutura.É desconhecido que receberá o thread de leitura de dados: os dados antigos, os dados gravados recentemente ou possivelmente uma mistura de ambos.MFC fornece um número de sincronização e classes de acesso de sincronização para ajudar na solução do problema.Este tópico explica as classes disponíveis e como usá-los para criar classes de thread-safe em um aplicativo multithread típico.

Um aplicativo multithread típico tem uma classe que representa um recurso para ser compartilhado entre segmentos.Uma classe projetada corretamente totalmente thread-safe não requer que você chame quaisquer funções de sincronização.Tudo é tratado internamente para a classe, permitindo que você se concentrar em como usar melhor a classe, não sobre como pode obter corrompido.É uma técnica eficaz para a criação de uma classe totalmente thread-safe mesclar a classe de sincronização na classe de recurso.Mesclando as classes de sincronização a classe compartilhada é um processo simples.

Por exemplo, levar um aplicativo mantém uma lista de contas.Este aplicativo permite que até três contas a ser examinado em janelas separadas, mas apenas um pode ser atualizado a qualquer momento específico.Quando uma conta é atualizada, os dados atualizados são enviados pela rede para um arquivo de dados.

Este aplicativo de exemplo usa os três tipos de classes de sincronização.Porque ele permite que até três contas a ser examinado, uma vez, ele usa CSemaphore para limitar o acesso aos três objetos de exibição.Quando uma tentativa de exibir uma quarta conta ocorre, o aplicativo ou aguarda até que o primeiro três janelas fecha ou ele falha.Quando uma conta é atualizada, o aplicativo usa CCriticalSection para garantir que apenas uma conta é atualizada ao mesmo tempo.Após a atualização for bem-sucedida, ele sinaliza CEvent, que libera um thread aguardando o evento ser sinalizado.Esse thread envia novos dados para o arquivamento de dados.

Criando uma classe de Thread-Safe

Para tornar uma classe totalmente thread-safe, adicione primeiro a classe de sincronização apropriado para classes compartilhadas como um membro de dados.No exemplo anterior de gerenciamento de conta, um CSemaphore membro de dados seria adicionado à classe de modo de exibição, um CCriticalSection membro de dados seria adicionado à classe lista vinculada e um CEvent membro de dados seria adicionado à classe de armazenamento de dados.

Em seguida, adicione chamadas de sincronização para todas as funções de membro que modifiquem os dados na classe ou acessam um recurso controlado.Em cada função, você deve criar um CSingleLock ou CMultiLock de objeto e chamar do objeto Lock função.Quando o objeto lock sai do escopo e é destruído, chama o destruidor do objeto Unlock , liberando os recursos.Claro, você pode chamar Unlock diretamente se desejar.

Criar sua classe thread-safe dessa maneira permite para ser usado em um aplicativo multithread como facilmente como uma classe de thread safe, mas com um nível maior de segurança.O objeto de sincronização e o objeto de sincronização de acesso de encapsulamento em classe do recurso fornece todos os benefícios de programação totalmente thread-safe sem o inconveniente de manter o código de sincronização.

O exemplo de código a seguir demonstra esse método usando um membro de dados m_CritSection (do tipo CCriticalSection), declarado na classe de recurso compartilhado e um CSingleLock objeto.A sincronização do recurso compartilhado (derivado de CWinThread) é tentada pela criação de um CSingleLock objeto usando o endereço a m_CritSection objeto.Uma tentativa de bloquear o recurso e, quando obtido, o trabalho é feito no objeto compartilhado.Quando o trabalho for concluído, o recurso está desbloqueado com uma chamada para Unlock.

CSingleLock singleLock(&m_CritSection);
singleLock.Lock();
// resource locked
//.usage of shared resource...

singleLock.Unlock();
ObservaçãoObservação

CCriticalSection, ao contrário de outras classes de sincronização do MFC, não tem a opção de uma solicitação de bloqueio de tempo limite.O período de espera por um segmento para se tornar livre é infinito.

As desvantagens dessa abordagem são que a classe será um pouco mais lenta do que a mesma classe sem objetos de sincronização adicionados.Além disso, se houver uma chance de que mais de um thread pode excluir o objeto, a abordagem mesclada pode nem sempre funcionar.Nessa situação, é melhor manter objetos de sincronização separada.

Para obter informações sobre como determinar qual classe de sincronização para usar em situações diferentes, consulte Multithreading: quando usar as Classes de sincronização.Para obter mais informações sobre sincronização, consulte sincronização na Windows SDK.Para obter mais informações sobre o suporte a multithreading no MFC, consulte Multithreading com C++ e MFC.

Consulte também

Conceitos

Multithreading com C++ e MFC