比較同步處理資料結構與 Windows API
本主題會比較並行執行階段所提供的同步處理資料結構與 Windows API 所提供的同步處理資料結構在行為上的差異。
並行執行階段所提供的同步處理資料結構是遵循「合作式執行緒模型」(Cooperative Threading Model)。 在合作式執行緒模型中,同步處理原始型別會將自己的處理資源讓給其他執行緒。 這不同於「先佔式執行緒模型」(Preemptive Threading Model),在該模型中,處理資源是由控制端排程器或作業系統轉給其他執行緒。
critical_section
concurrency::critical_section 類別與 Windows CRITICAL_SECTION 結構類似,因為只有同處理序的執行緒才能使用它。 如需 Windows API 中之關鍵區段的詳細資訊,請參閱關鍵區段物件。
reader_writer_lock
concurrency::reader_writer_lock 類別與 Windows 輕型讀取器/寫入器 (SRW) 鎖定類似。 下表說明相似和相異處。
功能 |
reader_writer_lock |
SRW 鎖定 |
---|---|---|
不可重新進入 |
有 |
有 |
可以將讀取器升階為寫入器 (升級支援) |
沒有 |
沒有 |
可以將寫入器降階為讀取器 (降級支援) |
沒有 |
沒有 |
寫入偏好設定鎖定 |
有 |
沒有 |
對寫入器的 FIFO 存取 |
有 |
沒有 |
如需 SRW 鎖定的詳細資訊,請參閱 Platform SDK 中的輕型讀取器/寫入器 (SRW) 鎖定。
event
concurrency::event 類別與未命名的 Windows 手動重設事件類似。 不過,event 物件是以合作方式運作,而 Windows 事件則是以先佔方式運作。 如需 Windows 事件的詳細資訊,請參閱事件物件。
範例
說明
若要更加了解 event 類別和 Windows 事件的差異,請參考下列範例。 這個範例會允許排程器最多建立兩個同時執行的工作,接著它會呼叫兩個類似的函式 (這兩個函式使用 event 類別和 Windows 手動重設事件)。 每個函式都會先建立數個工作,這些工作會等候某個共用事件變成已發出信號狀態。 每個函式接著會將資源讓給執行中的工作,然後發出事件的信號。 每個函式然後會等候所發出信號的事件。
程式碼
// 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();
}
註解
這個範例 (Example) 會產生下列範例 (Sample) 輸出:
因為 event 類別是以合作方式運作,所以排程器可以在有事件等候進入已發出信號狀態時,將處理資源重新配置給另一個內容。 因此,使用 event 類別的版本可以完成更多的工作。 在使用 Windows 事件的版本中,每個等候中的工作都必須先進入已發出信號狀態,下一個工作才會啟動。
如需工作的詳細資訊,請參閱 工作平行處理原則 (並行執行階段)。