Partilhar via


Comparando estruturas de dados de sincronização com a API do Windows

Este tópico compara o comportamento das estruturas de dados de sincronização fornecidas pelo Tempo de Execução de Simultaneidade com as fornecidas pela API do Windows.

As estruturas de dados de sincronização fornecidas pelo Concurrency Runtime seguem o modelo de threading cooperativo. No modelo de threading cooperativo, as primitivas de sincronização cedem explicitamente os seus recursos de processamento a outras threads. Isso difere do modelo de threading preventivo, onde os recursos de processamento são transferidos para outros threads pelo agendador de controle ou sistema operacional.

secção crítica

A classe concurrency::critical_section se assemelha à estrutura do Windows CRITICAL_SECTION porque pode ser usada apenas pelos threads de um processo. Para obter mais informações sobre seções críticas na API do Windows, consulte Objetos de seção crítica.

bloqueio de leitor/escritor

A classe concurrency::reader_writer_lock assemelha-se a bloqueios de leitor/gravador fino (SRW) do Windows. A tabela a seguir explica as semelhanças e diferenças.

Característica reader_writer_lock classe Bloqueio SRW
Não-reentrante Sim Sim
Pode promover um leitor a um escritor (suporte para atualização) Não Não
Pode rebaixar um escritor para um leitor (suporte a rebaixamento) Não Não
Bloqueio de preferência de gravação Sim Não
Acesso FIFO aos escritores Sim Não

Para obter mais informações sobre bloqueios SRW, consulte bloqueios leves de leitura/escrita (SRW) no Platform SDK.

evento

A classe concurrency::event assemelha-se a um evento manual-reset do Windows sem nome. No entanto, um event objeto se comporta cooperativamente, enquanto um evento do Windows se comporta preventivamente. Para obter mais informações sobre eventos do Windows, consulte Objetos de evento.

Exemplo

Descrição

Para entender melhor a diferença entre a classe e os event eventos do Windows, considere o exemplo a seguir. Este exemplo permite que o agendador crie no máximo duas tarefas simultâneas e, em seguida, chama duas funções semelhantes que utilizam a classe event e um evento de redefinição manual do Windows. Cada função primeiro cria várias tarefas que aguardam que um evento compartilhado seja sinalizado. Cada função então cede às tarefas em execução e, em seguida, sinaliza o evento. Em seguida, cada função aguarda o evento sinalizado.

Código

// event-comparison.cpp
// compile with: /EHsc
#include <windows.h>
#include <concrtrm.h>
#include <ppl.h>
#include <iostream>
#include <sstream>

using namespace concurrency;
using namespace std;

// Demonstrates the usage of cooperative events.
void RunCooperativeEvents()
{
   // An event object.
   event e;

   // Create a task group and execute five tasks that wait for
   // the event to be set.
   task_group tasks;
   for (int i = 0; i < 5; ++i)
   {
      tasks.run([&] {
         // Print a message before waiting on the event.
         wstringstream ss;
         ss << L"\t\tContext " << GetExecutionContextId() 
            << L": waiting on an event." << endl; 
         wcout << ss.str();

         // Wait for the event to be set.
         e.wait();

         // Print a message after the event is set.
         ss = wstringstream();
         ss << L"\t\tContext " << GetExecutionContextId() 
            << L": received the event." << endl; 
         wcout << ss.str();
      });
   }

   // Wait a sufficient amount of time for all tasks to enter 
   // the waiting state.
   Sleep(1000L);

   // Set the event.

   wstringstream ss;
   ss << L"\tSetting the event." << endl; 
   wcout << ss.str();

   e.set();

   // Wait for all tasks to complete.
   tasks.wait();
}

// Demonstrates the usage of preemptive events.
void RunWindowsEvents()
{
   // A Windows event object.
   HANDLE hEvent = CreateEvent(NULL, TRUE, FALSE, TEXT("Windows Event"));

   // Create a task group and execute five tasks that wait for
   // the event to be set.
   task_group tasks;
   for (int i = 0; i < 5; ++i)
   {
      tasks.run([&] {
         // Print a message before waiting on the event.
         wstringstream ss;
         ss << L"\t\tContext " << GetExecutionContextId() 
            << L": waiting on an event." << endl; 
         wcout << ss.str();

         // Wait for the event to be set.
         WaitForSingleObject(hEvent, INFINITE);

         // Print a message after the event is set.
         ss = wstringstream();
         ss << L"\t\tContext " << GetExecutionContextId() 
            << L": received the event." << endl; 
         wcout << ss.str();
      });
   }

   // Wait a sufficient amount of time for all tasks to enter 
   // the waiting state.
   Sleep(1000L);

   // Set the event.

   wstringstream ss;
   ss << L"\tSetting the event." << endl; 
   wcout << ss.str();

   SetEvent(hEvent);

   // Wait for all tasks to complete.
   tasks.wait();

   // Close the event handle.
   CloseHandle(hEvent);
}

int wmain()
{
   // Create a scheduler policy that allows up to two 
   // simultaneous tasks.
   SchedulerPolicy policy(1, MaxConcurrency, 2);

   // Attach the policy to the current scheduler.
   CurrentScheduler::Create(policy);
   
   wcout << L"Cooperative event:" << endl;
   RunCooperativeEvents();

   wcout << L"Windows event:" << endl;
   RunWindowsEvents();
}

Observações

Este exemplo produz a seguinte saída:

Cooperative event:
    Context 0: waiting on an event.
    Context 1: waiting on an event.
    Context 2: waiting on an event.
    Context 3: waiting on an event.
    Context 4: waiting on an event.
    Setting the event.
    Context 5: received the event.
    Context 6: received the event.
    Context 7: received the event.
    Context 8: received the event.
    Context 9: received the event.
Windows event:
    Context 10: waiting on an event.
    Context 11: waiting on an event.
    Setting the event.
    Context 12: received the event.
    Context 14: waiting on an event.
    Context 15: received the event.
    Context 16: waiting on an event.
    Context 17: received the event.
    Context 18: waiting on an event.
    Context 19: received the event.
    Context 13: received the event.

Como a event classe se comporta cooperativamente, o agendador pode realocar recursos de processamento para outro contexto quando um evento está aguardando para entrar no estado sinalizado. Portanto, mais trabalho é realizado pela versão que usa a event classe. Na versão que usa eventos do Windows, cada tarefa em espera deve entrar no estado sinalizado antes que a próxima tarefa seja iniciada.

Para obter mais informações sobre tarefas, consulte Paralelismo de tarefas.

Ver também

Estruturas de dados de sincronização