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.