Поделиться через


Сравнение структур данных синхронизации с интерфейсом Windows API

В этом разделе сравнивается поведение структур данных синхронизации, предоставленных средой выполнения с параллелизмом и интерфейсом Windows API.

Структуры данных синхронизации, предоставленные средой выполнения с параллелизмом, созданы по модели совместных потоков. В модели совместных потоков примитивы синхронизации явно передают ресурсы для обработки другим потокам. Этим она отличается от модели потоков с вытеснением, в которой ресурсы для обработки передаются другим потокам управляющим планировщиком или операционной системой.

critical_section

Класс Concurrency::critical_section напоминает структуру CRITICAL_SECTION Windows, потому что он может использоваться только потоками одного процесса. Дополнительные сведения о критических секциях в интерфейсе Windows API см. в разделе Объекты критических секций.

reader_writer_lock

Класс Concurrency::reader_writer_lock напоминает тонкие блокировки чтения и записи (SRW) Windows. В следующей таблице перечислены сходства и различия этих сущностей.

Функция

reader_writer_lock

Блокировка SRW

Повторные входы недопустимы

Да

Да

Возможность повысить уровень средства чтения до уровня средства записи (поддержка обновлений)

Нет

Нет

Возможность понизить уровень средства записи до уровня средства чтения (поддержка понижения уровня)

Нет

Нет

Блокировка предпочтения записи

Да

Нет

Доступ к средствам записи по методу FIFO

Да

Нет

Дополнительные сведения о блокировках SRW см. в разделе Тонкие блокировки чтения/записи (SRW) в пакете SDK данной платформы.

event

Класс Concurrency::event напоминает неименованное событие ручного сброса Windows. Однако объект event предназначен для использования в совместных сценариях, а событие Windows — в сценариях вытеснения. Дополнительные сведения о событиях Windows см. в разделе Объекты Event.

Пример

Описание

Чтобы лучше понять разницу между классом 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, каждая ожидающая задача должна перейти в сигнальное состояние, прежде чем будет запущена следующая задача.

Дополнительные сведения о задачах см. в разделе Параллелизм задач (среда выполнения с параллелизмом).

См. также

Ссылки

Объекты критичных участков

Тонкие блокировки чтения и записи (SRW)

Объекты событий

Основные понятия

Структуры данных синхронизации