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


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

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

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

critical_section

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

reader_writer_lock

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

Функция Класс reader_writer_lock Блокировка SRW
Без повторного входа Да Да
Может повысить уровень чтения в средство записи (поддержка обновления) No No
Может понижение записи на средство чтения (поддержка понижения) No No
Блокировка предпочтения записи Да Нет
Доступ FIFO к писателям Да Нет

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

события

Класс событий параллелизма::event похож на событие без имени, событие сброса вручную Windows. Однако объект ведет себя совместно, event в то время как событие Windows ведет себя заранее. Дополнительные сведения о событиях Windows см. в разделе "Объекты событий".

Пример

Description

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

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

См. также

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