Partilhar via


Sincronizando a execução de vários threads

Para evitar situações de corrida e interbloqueios, é necessário sincronizar o acesso de vários threads aos recursos partilhados. A sincronização também é necessária para garantir que o código interdependente seja executado na sequência adequada.

Há uma série de objetos cujos identificadores podem ser usados para sincronizar vários threads. Esses objetos incluem:

  • Buffers de entrada do console
  • Eventos
  • Mutexes
  • Processos
  • Semáforos
  • Tópicos
  • Temporizadores

O estado de cada um desses objetos é sinalizado ou não sinalizado. Quando você especifica um identificador para qualquer um desses objetos em uma chamada para uma das funções de espera , a execução do thread de chamada é bloqueada até que o estado do objeto especificado seja sinalizado.

Alguns desses objetos são úteis para bloquear um thread até que algum evento ocorra. Por exemplo, uma alça de buffer de entrada do console é sinalizada quando há entrada não lida, como pressionamento de tecla ou clique no botão do mouse. Os identificadores de processo e de thread são sinalizados quando o processo ou thread termina. Isso permite que um processo, por exemplo, crie um processo filho e, em seguida, bloqueie a sua própria execução até que o novo processo tenha terminado.

Outros objetos são úteis para proteger recursos compartilhados do acesso simultâneo. Por exemplo, vários threads podem ter um identificador para um objeto mutex. Antes de aceder a um recurso compartilhado, as threads devem chamar uma das funções wait para aguardar que o estado do mutex seja sinalizado. Quando o mutex é sinalizado, apenas uma thread de espera é liberada para aceder ao recurso. O estado do mutex é imediatamente redefinido para não sinalizar, para que qualquer outra thread de espera permaneça bloqueada. Quando o thread termina com o recurso, ele deve definir o estado do mutex como sinalizado para permitir que outros threads acessem o recurso.

Para os threads de um único processo, os objetos de seção crítica fornecem um meio mais eficiente de sincronização do que os mutexes. Uma seção crítica é usada como um mutex para permitir que um thread de cada vez use o recurso protegido. Um thread pode usar a função EnterCriticalSection para solicitar a propriedade de uma seção crítica. Se já pertencer a outro thread, o thread solicitante será bloqueado. Um thread pode usar a função TryEnterCriticalSection para solicitar a propriedade de uma seção crítica, sem bloquear em caso de falha na obtenção da seção crítica. Depois de receber a propriedade, o thread fica livre para usar o recurso protegido. A execução dos outros threads do processo não é afetada, a menos que eles tentem entrar na mesma seção crítica.

A funçãoWaitForInputIdle faz com que um thread aguarde até que um processo especificado seja inicializado e aguarde a entrada do usuário sem nenhuma entrada pendente. Chamar WaitForInputIdle pode ser útil para sincronizar processos pai e filho, porque CreateProcess retorna sem esperar que o processo filho conclua sua inicialização.

Para obter mais informações, consulte Sincronização.