Jämföra synkroniseringsdatastrukturer med Windows-API:et

I det här avsnittet jämförs beteendet för de synkroniseringsdatastrukturer som tillhandahålls av Concurrency Runtime med de som tillhandahålls av Windows-API:et.

De synkroniseringsdatastrukturer som tillhandahålls av Concurrency Runtime följer samarbetstrådsmodellen. I den samarbetsinriktade trådmodellen ger synkroniseringspri primitiver uttryckligen sina bearbetningsresurser till andra trådar. Detta skiljer sig från den förebyggande trådningsmodellen, där bearbetningsresurser överförs till andra trådar av den kontrollerande schemaläggaren eller operativsystemet.

kritisk sektion

Klassen concurrency::critical_section liknar Windows-strukturen CRITICAL_SECTION eftersom den endast kan användas av trådarna i en process. Mer information om kritiska avsnitt i Windows-API:et finns i Kritiska avsnittsobjekt.

läsare-skrivarlås

Klassen concurrency::reader_writer_lock liknar SRW-lås (Windows slim reader/writer). I följande tabell förklaras likheterna och skillnaderna.

Funktion reader_writer_lock klass SRW-lås
Icke-återinträdesbar Ja Ja
Kan höja upp en läsare till en skrivare (uppgraderingsstöd) Nej Nej
Kan nedgradera en författare till en läsare (stöd för nedgradering) Nej Nej
Lås för skrivinställningar Ja Nej
FIFO-åtkomst till skrivare Ja Nej

Mer information om SRW-lås finns i SRW-lås (Slim Reader/Writer) i Platform SDK.

händelse

Concurrency::event-klassen liknar en namnlös Windows-händelse för manuell återställning. Ett event objekt samverkar dock, medan en Windows-händelse fungerar förhandsmässigt. Mer information om Windows-händelser finns i Händelseobjekt.

Exempel

Beskrivning

Tänk på följande exempel för att bättre förstå skillnaden mellan event klass- och Windows-händelser. I det här exemplet kan schemaläggaren skapa högst två samtidiga uppgifter och anropar sedan två liknande funktioner som använder event klassen och en händelse för manuell återställning av Windows. Varje funktion skapar först flera uppgifter som väntar på att en delad händelse ska signaleras. Varje funktion ger plats åt de uppgifter som körs och signalerar sedan händelsen. Varje funktion väntar sedan på den signalerade händelsen.

Kod

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

Kommentarer

I det här exemplet skapas följande exempelutdata:

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.

event Eftersom klassen fungerar tillsammans kan schemaläggaren omallokera bearbetningsresurser till en annan kontext när en händelse väntar på att ange det signalerade tillståndet. Därför utförs mer arbete av den version som använder event klassen. I den version som använder Windows-händelser måste varje väntande uppgift ange det signalerade tillståndet innan nästa uppgift startas.

Mer information om aktiviteter finns i Aktivitetsparallellitet.

Se även

Datastrukturer för synkronisering