Udostępnij za pośrednictwem


Porównywanie struktur danych synchronizacji z Windows API

W tym temacie porównaliśmy zachowanie struktur danych synchronizacji udostępnianych przez środowisko uruchomieniowe współbieżności do tych dostarczonych przez interfejs API systemu Windows.

Struktury danych synchronizacji udostępniane przez środowisko uruchomieniowe współbieżności są zgodne z modelem współpracy wątkowości. W modelu wątków współpracy typy pierwotne synchronizacji jawnie dają zasoby przetwarzania innym wątkom. Różni się to od modelu wielowątkowego, w którym zasoby przetwarzania są przenoszone do innych wątków przez harmonogram sterowania lub system operacyjny.

critical_section

Klasa concurrency::critical_section przypomina strukturę systemu Windows CRITICAL_SECTION , ponieważ może być używana tylko przez wątki jednego procesu. Aby uzyskać więcej informacji na temat krytycznych sekcji w interfejsie API systemu Windows, zobacz Sekcje krytyczne Obiekty.

Klasa reader_writer_lock

Klasa concurrency::reader_writer_lock przypomina blokady windows slim reader/writer (SRW). W poniższej tabeli opisano podobieństwa i różnice.

Funkcja Klasa reader_writer_lock Blokada SRW
Non-reentrant Tak Tak
Może podwyższyć poziom czytelnika do modułu zapisywania (obsługa uaktualniania) Nie. Nie.
Może obniżyć poziom zapisywania do czytelnika (obsługa obniżania poziomu) Nie. Nie.
Blokada preferencji zapisu Tak Nie.
Dostęp FIFO do składników zapisywania Tak Nie.

Aby uzyskać więcej informacji na temat blokad SRW, zobacz Slim Reader/Writer (SRW) Locks in the Platform SDK (Slim Reader/Writer( SRW) Locks in the Platform SDK (Slim Reader/Writer, SRW).

event

Klasa concurrency::event przypomina nienazwane zdarzenie ręcznego resetowania systemu Windows. event Jednak obiekt zachowuje się kooperacyjnie, podczas gdy zdarzenie systemu Windows zachowuje się z góry. Aby uzyskać więcej informacji na temat zdarzeń systemu Windows, zobacz Event Objects (Obiekty zdarzeń).

Przykład

opis

Aby lepiej zrozumieć różnicę między klasą event i zdarzeniami systemu Windows, rozważ poniższy przykład. W tym przykładzie harmonogram umożliwia utworzenie co najwyżej dwóch równoczesnych zadań, a następnie wywołanie dwóch podobnych funkcji korzystających z event klasy i zdarzenia ręcznego resetowania systemu Windows. Każda funkcja najpierw tworzy kilka zadań, które oczekują na sygnał zdarzenia udostępnionego. Następnie każda funkcja zwraca uruchomione zadania, a następnie sygnalizuje zdarzenie. Następnie każda funkcja czeka na zasygnalizowane zdarzenie.

Kod

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

Komentarze

W tym przykładzie są generowane następujące przykładowe dane wyjściowe:

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 Ponieważ klasa zachowuje się wspólnie, harmonogram może ponownie przydzielić zasoby przetwarzania do innego kontekstu, gdy zdarzenie oczekuje na wprowadzenie stanu zasygnalizowanego. W związku z tym większa praca jest osiągana przez wersję, która używa event klasy . W wersji używającej zdarzeń systemu Windows każde zadanie oczekujące musi wprowadzić stan zasygnalizowany przed rozpoczęciem następnego zadania.

Aby uzyskać więcej informacji na temat zadań, zobacz Równoległość zadań.

Zobacz też

Struktury danych synchronizacji