将同步数据结构与 Windows API 进行比较
本主题将并发运行时提供的同步数据结构的行为与 Windows API 提供的同步数据结构的行为进行比较。
并发运行时提供的同步数据结构效仿协作式线程模型。 在协作式线程模型中,同步基元将其处理资源显式让给其他线程。 这不同于抢先式线程模型,在该模型中,处理资源由控制计划程序或操作系统传输给其他线程。
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 锁的更多信息,请参见平台 SDK 中的轻量级读取器/编写器 (SRW) 锁。
事件
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();
}
注释
此示例产生下面的示例输出:
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 类以协作方式工作,所以当事件等待进入终止状态时,计划程序可以将处理资源重新分配给另一个上下文。 因此,使用 event 类的版本将完成更多的工作。 在使用 Windows 事件的版本中,每个正在等待的任务必须进入终止状态,下一个任务才能开始。
有关任务的更多信息,请参见任务并行(并发运行时)。