Vergleich der Synchronisierungsdatenstrukturen mit der Windows-API

In diesem Thema wird das Verhalten der von der Concurrency Runtime bereitgestellten Synchronisierungsdatenstrukturen mit den von der Windows-API bereitgestellten Synchronisierungsdatenstrukturen verglichen.

Die von der Concurrency Runtime bereitgestellten Synchronisierungsdatenstrukturen basieren auf dem kooperativen Threadingmodell. Im kooperativen Threadingmodell halten Synchronisierungsprimitiven ihre Verarbeitungsressourcen zugunsten von anderen Threads explizit zurück. Dies unterscheidet sich vom präemptiven Threadingmodell, bei dem Verarbeitungsressourcen vom Planer oder vom Betriebssystem an andere Threads übergeben werden.

critical_section

Die Concurrency::critical_section-Klasse ähnelt der CRITICAL_SECTION-Struktur in Windows, da sie nur von den Threads eines Prozesses verwendet werden kann. Weitere Informationen zu kritischen Abschnitten in der Windows-API finden Sie unter Critical Section Objects.

reader_writer_lock

Die Concurrency::reader_writer_lock-Klasse ähnelt der Reader-/Writer-Sperre (Slim Reader/Writer, SRW) in Windows. In der folgenden Tabelle werden die Übereinstimmungen und Unterschiede aufgelistet.

Feature

reader_writer_lock

SRW-Sperre

Nicht wiedereintretend

Ja

Ja

Kann einen Reader auf einen Writer hochstufen

nein

nein

Kann einen Writer auf einen Reader tieferstufen

nein

nein

write-preference-Sperre

ja

nein

FIFO-Zugriff auf Writer

ja

nein

Weitere Informationen zu SRW-Sperren finden Sie unter Slim Reader/Writer (SRW) Locks im Platform SDK.

event

Die Concurrency::event-Klasse ähnelt einem nicht benannten Ereignis für manuelles Zurücksetzen in Windows. Das Verhalten eines event-Objekts ist jedoch kooperativ, das Verhalten eines Windows-Ereignisses hingegen präemptiv. Weitere Informationen zu Windows-Ereignissen finden Sie unter Event Objects.

Beispiel

Beschreibung

Das folgende Beispiel soll den Unterschied zwischen der event-Klasse und Windows-Ereignissen verdeutlichen. In diesem Beispiel wird der Planer aktiviert, um höchstens zwei gleichzeitige Aufgaben zu erstellen. Anschließend werden zwei ähnliche Funktionen aufgerufen, die die event-Klasse und ein Ereignis für manuelles Zurücksetzen in Windows verwenden. Beide Funktionen erstellen zunächst mehrere Aufgaben, die auf die Signalisierung eines freigegebenen Ereignisses warten. Beide Funktionen halten dann die ausgeführten Aufgaben zurück und signalisieren das Ereignis. Beide Funktionen warten dann auf das signalisierte Ereignis.

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

Kommentare

Dieses Beispiel erzeugt die folgende Beispielausgabe:

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.

Da das Verhalten der event-Klasse kooperativ ist, kann der Planer Verarbeitungsressourcen einem anderen Kontext zuweisen, während auf die Signalisierung eines Ereignisses gewartet wird. Aus diesem Grund bewerkstelligt die Version, die die event-Klasse verwendet, einen höheren Arbeitsaufwand. In der Version, die Windows-Ereignisse verwendet, muss jede wartende Aufgabe den signalisierten Zustand aufweisen, bevor die nächste Aufgabe gestartet werden kann.

Weitere Informationen zu Aufgaben finden Sie unter Aufgabenparallelität (Concurrency Runtime).

Siehe auch

Referenz

Objekte für kritische Abschnitte

SRW (Slim Reader/Writer)-Sperren

Ereignisobjekte

Konzepte

Synchronisierungsdatenstrukturen