Compartir a través de


Comparar estructuras de datos de sincronización con la API de Windows

En este tema se compara el comportamiento de las estructuras de datos de sincronización que proporciona el Runtime de simultaneidad con las que proporciona la API de Windows.

Las estructuras de datos de sincronización que proporciona el Runtime de simultaneidad siguen el modelo de subprocesos cooperativo. En este modelo, las primitivas de sincronización ceden explícitamente sus recursos de procesamiento a otros subprocesos. Esto lo diferencia del modelo de subprocesos preferente, donde los recursos de procesamiento se transfieren a otros subprocesos por medio del programador de control o el sistema operativo.

critical_section

La clase concurrency::critical_section es similar a la estructura CRITICAL_SECTION de Windows, ya que solamente la pueden usar los subprocesos de un proceso. Para obtener más información sobre las secciones críticas en la API de Windows, vea Objetos de sección crítica.

reader_writer_lock

La clase concurrency::reader_writer_lock es similar a los bloqueos SRW (bloqueos finos de lector/escritor) de Windows. En la tabla siguiente se explican las similitudes y las diferencias.

Característica Clase reader_writer_lock Bloqueo SRW
No reentrante
Puede promover un lector a un escritor (compatibilidad de actualización) No No
Puede degradar un escritor a un lector (compatibilidad de degradación) No No
Bloqueo de preferencia de escritura No
Acceso FIFO a escritores No

Para obtener más información sobre los bloqueos SRW, vea Bloqueos SRW (bloqueos finos de lector/escritor) en Platform SDK.

event

La clase concurrency::event es similar a un evento de restablecimiento manual sin nombre de Windows. Sin embargo, un objeto event se comporta de forma cooperativa, en tanto que un evento de Windows se comporta con preferencia. Para obtener más información sobre los eventos de Windows, vea Objetos de eventos.

Ejemplo

Descripción

Para comprender mejor la diferencia entre la clase de event y los eventos de Windows, considere el siguiente ejemplo. Este ejemplo permite que el programador cree dos tareas simultáneas a lo sumo y, a continuación, llama a dos funciones similares que utilizan la clase event y un evento de restablecimiento manual de Windows. Cada función crea en primer lugar varias tareas que esperan hasta que se señaliza un evento compartido. A continuación, cada función cede el paso a las tareas en ejecución y, después, señala el evento. Posteriormente, cada función espera por el evento señalado.

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();
}

Comentarios

Este ejemplo genera la siguiente salida de ejemplo:

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.

La clase event se comporta de forma cooperativa, por lo que el programador puede reasignar los recursos del procesamiento a otro contexto cuando un evento está esperando para entrar en el estado señalado. Así, la versión que utiliza la clase event realiza más trabajo. En la versión que utiliza los eventos de Windows, cada tarea de espera debe entrar en el estado señalado antes de que se inicie la tarea siguiente.

Para obtener más información sobre las tareas, consulte Paralelismo de tareas.

Consulte también

Estructuras de datos de sincronización