동기화 데이터 구조와 Windows API의 비교

이 항목에서는 동시성 런타임에서 제공하는 동기화 데이터 구조의 동작과 Windows API에서 제공하는 동작을 비교합니다.

동시성 런타임에서 제공하는 동기화 데이터 구조는 협조적 스레딩 모델을 따릅니다. 협조적 스레딩 모델에서 동기화 기본 형식은 처리 리소스를 다른 스레드에 명시적으로 생성합니다. 이는 제어 스케줄러 또는 운영 체제에 의해 처리 리소스가 다른 스레드로 전송되는 선점 스레딩 모델과 다릅니다.

critical_section

동시성::critical_section 클래스는 한 프로세스의 스레드에서만 사용할 수 있으므로 Windows CRITICAL_SECTION 구조체와 유사합니다. Windows API의 중요한 섹션에 대한 자세한 내용은 중요 섹션 개체를 참조 하세요.

reader_writer_lock

동시성::reader_writer_lock 클래스는 Windows SRW(슬림 판독기/기록기) 잠금과 유사합니다. 다음 표에서는 유사점과 차이점을 설명합니다.

기능 reader_writer_lock 클래스 SRW 잠금
재진입하지 않는 경우
판독기를 작성기에 승격할 수 있습니다(업그레이드 지원) 아니요 아니요
작성기를 판독기로 강등할 수 있습니다(지원 다운그레이드). 아니요 아니요
쓰기 기본 설정 잠금 아니요
작성기에 대한 FIFO 액세스 아니요

SRW 잠금에 대한 자세한 내용은 플랫폼 SDK의 SRW(Slim Reader/Writer) 잠금을 참조하세요.

event

concurrency::event 클래스는 명명되지 않은 Windows 수동 재설정 이벤트와 유사합니다. 그러나 개체는 event 협조적으로 동작하는 반면 Windows 이벤트는 선제적으로 동작합니다. Windows 이벤트에 대한 자세한 내용은 이벤트 개체를 참조 하세요.

예제

설명

클래스와 Windows 이벤트의 차이점을 event 더 잘 이해하려면 다음 예제를 고려하세요. 이 예제에서는 스케줄러가 최대 두 개의 동시 작업을 만든 다음 클래스와 Windows 수동 재설정 이벤트를 사용하는 event 두 개의 유사한 함수를 호출할 수 있도록 합니다. 각 함수는 먼저 공유 이벤트가 신호를 받기를 기다리는 여러 작업을 만듭니다. 그런 다음 각 함수는 실행 중인 작업에 대해 생성한 다음 이벤트를 신호로 표시합니다. 그런 다음 각 함수는 신호를 받은 이벤트를 기다립니다.

코드

// 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 이벤트를 사용하는 버전에서 대기 중인 각 작업은 다음 작업이 시작되기 전에 신호 상태를 입력해야 합니다.

작업에 대한 자세한 내용은 작업 병렬 처리를 참조하세요.

참고 항목

동기화 데이터 구조