Comparaison des 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 threading coopératif. Dans le modèle de thread de coopération, les primitives de synchronisation produisent explicitement leurs ressources de traitement à d’autres threads. Cela diffère du modèle de thread préemptive, où les ressources de traitement sont transférées vers d’autres threads par le planificateur de contrôle ou le système d’exploitation.
critical_section
La classe concurrency ::critical_section ressemble à la structure Windows CRITICAL_SECTION
, car elle ne peut être utilisée que par les threads d’un processus. Pour plus d’informations sur les sections critiques de l’API Windows, consultez Objets de section critique.
reader_writer_lock
La classe concurrency ::reader_writer_lock ressemble aux verrous de lecteur/enregistreur (SRW) Windows minces. Le tableau suivant explique les similitudes et les différences.
Fonction | Classe reader_writer_lock |
Verrou SRW |
---|---|---|
Non-reentrant | Oui | Oui |
Peut promouvoir un lecteur vers un enregistreur (prise en charge de la mise à niveau) | No | No |
Peut rétrograder un enregistreur vers un lecteur (prise en charge de la rétrogradation) | No | No |
Verrou de préférence d’écriture | Oui | No |
Accès FIFO aux écrivains | Oui | No |
Pour plus d’informations sur les verrous SRW, consultez Verrous de lecteur/enregistreur (SRW) slim dans le Kit de développement logiciel (SDK) de plateforme.
événement
La classe concurrency ::event ressemble à un événement de réinitialisation manuelle Windows sans nom. Toutefois, un event
objet se comporte de manière coopérative, tandis qu’un événement Windows se comporte de manière préemptive. Pour plus d’informations sur les événements Windows, consultez Objets d’événements.
Exemple
Description
Pour mieux comprendre la différence entre la event
classe et les événements Windows, considérez l’exemple suivant. Cet exemple permet au planificateur de créer au maximum deux tâches simultanées, puis appelle deux fonctions similaires qui utilisent la event
classe et un événement de réinitialisation manuelle Windows. Chaque fonction crée d’abord plusieurs tâches qui attendent qu’un événement partagé devienne signalé. Chaque fonction retourne 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 produit 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 event
classe se comporte de manière coopérative, le planificateur peut réallouer des ressources de traitement vers un autre contexte lorsqu’un événement attend d’entrer l’état signalé. Par conséquent, plus de travail est effectué par la version qui utilise la event
classe. Dans la version qui utilise des événements Windows, chaque tâche en attente doit entrer l’état signalé avant le démarrage de la tâche suivante.
Pour plus d’informations sur les tâches, consultez Parallélisme des tâches.