比較同步處理資料結構與 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 事件的詳細資訊,請參閱事件物件

範例

Dd759350.collapse_all(zh-tw,VS.110).gif描述

若要更加了解 event 類別和 Windows 事件的差異,請參考下列範例。這個範例會允許排程器最多建立兩個同時執行的工作,接著它會呼叫兩個類似的函式 (這兩個函式使用 event 類別和 Windows 手動重設事件)。每個函式都會先建立數個工作,這些工作會等候某個共用事件變成已發出信號狀態。每個函式接著會將資源讓給執行中的工作,然後發出事件的信號。每個函式然後會等候所發出信號的事件。

Dd759350.collapse_all(zh-tw,VS.110).gif程式碼

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

Dd759350.collapse_all(zh-tw,VS.110).gif註解

這個範例 (Example) 會產生下列範例 (Sample) 輸出:

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 事件的版本中,每個等候中的工作都必須先進入已發出信號狀態,下一個工作才會啟動。

如需工作的詳細資訊,請參閱工作平行處理原則 (並行執行階段)

請參閱

參考

關鍵區段物件

輕型讀取器/寫入器 (SRW) 鎖定

事件物件

概念

同步處理資料結構