Compartilhar via


Comparando estruturas de dados com a API do Windows

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

As estruturas de dados de sincronização fornecidas pelo Runtime de Simultaneidade seguem o modelo de threading cooperativo. No modelo de threading cooperativo, os primitivos de sincronização geram explicitamente seus recursos de processamento para outros threads. Isso difere do modelo de threading preemptivo, em que os recursos de processamento são transferidos para outros threads pelo agendador de controle ou pelo sistema operacional.

critical_section

A classe concurrency::critical_section se assemelha à estrutura do Windows CRITICAL_SECTION porque ela só pode ser usada 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íticos.

reader_writer_lock

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

Recurso Classe reader_writer_lock Bloqueio SRW
Não reentrante Sim Sim
Pode promover um leitor a gravador (suporte de atualização) Não No
Pode rebaixar um gravador a leitor (suporte a downgrade) Não No
Bloqueio de preferência de gravação Sim No
Acesso FIFO aos gravadores Sim No

Para obter mais informações sobre bloqueios SRW, consulte Bloqueios finos SRW (leitor/gravador) no SDK da plataforma.

event

A classe concurrency::event se assemelha a um evento de redefinição manual do Windows sem nome. No entanto, um objeto event 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 event e 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 usam a classe event e um evento de redefinição manual do Windows. Cada função primeiro cria várias tarefas que esperam que um evento compartilhado seja sinalizado. Cada função, em seguida, produz para as tarefas em execução e então sinaliza o evento. Cada função aguarda então 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();
}

Comentários

Este exemplo gera a seguinte saída de amostra:

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 classe event se comporta cooperativamente, o agendador pode realocar recursos de processamento para outro contexto quando um evento está esperando para entrar no estado assinado. Portanto, mais trabalho é realizado pela versão que usa a classe event. Na versão que usa eventos do Windows, cada tarefa de espera deve inserir o estado assinado antes que a próxima tarefa seja iniciada.

Para obter mais informações sobre grupos de tarefas, confira Paralelismo de Tarefa.

Confira também

Estruturas de dados de sincronização