Partager via


Comparaison de structures de données de synchronisation avec l'API Windows

Cette rubrique compare le comportement des structures de données de synchronisation fournies par le runtime d'accès concurrentiel à celles fournies par l'API Windows.

Les structures de données de synchronisation fournies par le runtime d'accès concurrentiel suivent le modèle de thread coopératif. Dans le modèle de thread coopératif, les primitives de synchronisation cèdent explicitement leurs ressources de traitement à d'autres threads. Cela diffère du modèle de thread préemptif, selon lequel les ressources de traitement sont transférées à d'autres threads par le système d'exploitation ou le planificateur de contrôle.

critical_section

La classe Concurrency::critical_section s'apparente à la structure CRITICAL_SECTION Windows, car elle peut uniquement être utilisée par les threads d'un seul processus. Pour plus d'informations sur les sections critiques dans l'API Windows, consultez Objets de section critique.

reader_writer_lock

La classe Concurrency::reader_writer_lock s'apparente aux verrous SRW (Slim Reader/Writer) de Windows. Le tableau suivant explique quelles sont les similarités et les différences.

Fonctionnalité

reader_writer_lock

Verrou SRW

Non réentrant

Oui

Oui

Peut promouvoir un lecteur en enregistreur (prise en charge de la mise à niveau)

Non

Non

Peut rétrograder un enregistreur en lecteur (prise en charge de la rétrogradation)

Non

Non

Verrou à préférence d'écriture

Oui

Non

Accès FIFO aux enregistreurs

Oui

Non

Pour plus d'informations sur les verrous SRW, consultez la rubrique sur les verrous SRW (Slim Reader/Writer) dans le Kit de développement Platform SDK.

event

La classe Concurrency::event s'apparente à un événement Windows à réinitialisation manuelle sans nom. Toutefois, un objet event se comporte de manière coopérative, alors qu'un événement Windows se comporte de manière préemptive. Pour plus d'informations sur les événements Windows, consultez Objets événements.

Exemple

Description

Pour mieux comprendre la différence entre la classe event et les événements Windows, considérez l'exemple suivant. Cet exemple permet au planificateur de créer au plus deux tâches simultanées, puis il appelle deux fonctions semblables qui utilisent la classe event et un événement Windows à réinitialisation manuelle. Chaque fonction crée d'abord plusieurs tâches qui attendent qu'un événement partagé soit signalé. Chaque fonction cède ensuite aux tâches en cours d'exécution, puis signale l'événement. Chaque fonction attend ensuite l'événement signalé.

Code

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

Commentaires

Cet exemple génère l'exemple de sortie suivant :

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.

Étant donné que la classe event se comporte de manière coopérative, le planificateur peut réaffecter les ressources de traitement à un autre contexte lorsqu'un événement attend de passer à l'état signalé. Par conséquent, davantage de travail est accompli par la version qui utilise la classe event. Dans la version qui utilise des événements Windows, chaque tâche en attente doit passer à l'état signalé avant que la tâche suivante soit démarrée.

Pour plus d'informations sur les tâches, consultez Parallélisme des tâches (runtime d'accès concurrentiel).

Voir aussi

Référence

Objets de section critique

Verrous SRW (Slim Reader/Writer)

Objets événement

Concepts

Structures de données de synchronisation