Sdílet prostřednictvím


Porovnávání synchronizačních datových struktur s rozhraním API systému Windows

Toto téma porovnává chování synchronizačních datových struktur poskytovaných modulem Concurrency Runtime s těmi, které poskytuje rozhraní API systému Windows.

Synchronizační datové struktury poskytované modulem Concurrency Runtime se řídí modelem kooperativního vlákna. V modelu kooperativního vlákna primitiva synchronizace explicitně poskytují své prostředky zpracování do jiných vláken. To se liší od modelu preemptive threading, kde jsou prostředky zpracování přeneseny do jiných vláken pomocí řídicího plánovače nebo operačního systému.

critical_section

Concurrency::critical_section třída se podobá struktuře WindowsCRITICAL_SECTION, protože ji mohou používat pouze vlákna jednoho procesu. Další informace o kritických oddílech v rozhraní API systému Windows naleznete v tématu Kritické objekty oddílu.

reader_writer_lock

Concurrency ::reader_writer_lock třída se podobá zámkům srW (Slim Reader/Writer) systému Windows. Následující tabulka vysvětluje podobnosti a rozdíly.

Funkce Třída reader_writer_lock Zámek SRW
Nesdělí se znovu Ano Yes
Může zvýšit úroveň čtenáře na zapisovač (podpora upgradu) No Ne
Může snížit úroveň zapisovače na čtenáře (podpora downgradu) No Ne
Zámek předvoleb zápisu Yes No
Přístup FIFO k zapisovačům Yes No

Další informace o zámcích SRW naleznete v tématu Slim Reader/Writer (SRW) Zámky v sadě SDK platformy.

event

Třída concurrency::event se podobá nepojmenované události ručního resetování Systému Windows. Objekt event se ale chová spolu, zatímco událost Systému Windows se chová předem. Další informace o událostech systému Windows naleznete v tématu Objekty událostí.

Příklad

Popis

Pokud chcete lépe porozumět rozdílu event mezi událostmi třídy a Windows, zvažte následující příklad. Tento příklad umožňuje plánovači vytvořit maximálně dva souběžné úlohy a potom volá dvě podobné funkce, které používají event třídu a událost ručního resetování Systému Windows. Každá funkce nejprve vytvoří několik úkolů, které čekají na signál sdílené události. Každá funkce pak získá spuštěné úlohy a pak signalizuje událost. Každá funkce pak čeká na signalovanou událost.

Kód

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

Komentáře

Tento příklad vytvoří následující ukázkový výstup:

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.

Vzhledem k tomu, že se event třída chová spolu, může plánovač relokovat prostředky zpracování do jiného kontextu, když událost čeká na vstup do signalovaného stavu. Proto je více práce dosaženo verzí, která používá event třídu. Ve verzi, která používá události Systému Windows, musí každá čekající úloha zadat stav signálu před spuštěním dalšího úkolu.

Další informace o úkolech naleznete v tématu Paralelismus úkolu.

Viz také

Synchronizační datové struktury