Confronto delle strutture di dati di sincronizzazione con l'API Windows

In questo argomento viene confrontato il comportamento delle strutture di dati di sincronizzazione fornite dal runtime di concorrenza con quelle fornite dall'API Windows.

Le strutture di dati di sincronizzazione fornite dal runtime di concorrenza seguono il modello di threading cooperativo. Nel modello di threading cooperativo, le primitive di sincronizzazione restituiscono in modo esplicito le risorse di elaborazione agli altri thread. Questo modello è diverso dal modello di threading di tipo preemptive, dove le risorse di elaborazione vengono trasferite agli altri thread dall'utilità di pianificazione di controllo o dal sistema operativo.

critical_section

La classe Concurrency::critical_section è simile alla struttura CRITICAL_SECTION di Windows poiché può essere utilizzata solo dai thread di un processo. Per ulteriori informazioni sulle sezioni critiche nell'API Windows, vedere Oggetti sezione critica (la pagina potrebbe essere in inglese).

reader_writer_lock

La classe Concurrency::reader_writer_lock è simile ai blocchi in lettura scrittura ridotti (SRW) di Windows. Nella tabella seguente vengono illustrate similitudini e differenze.

Funzionalità

reader_writer_lock

Blocco SRW

Non rientrante

Possibilità di promuovere da reader a writer (supporto dell'aggiornamento)

No

No

Possibilità di abbassare di livello da writer a reader (supporto del downgrade)

No

No

Blocco preferenza scrittura

No

Accesso FIFO ai writer

No

Per ulteriori informazioni sui blocchi SRW, vedere Blocchi in lettura/scrittura ridotti (SRW) (la pagina potrebbe essere in inglese) in Platform SDK.

event

La classe Concurrency::event è simile a un evento Windows di reimpostazione manuale senza nome. Tuttavia, un oggetto event si comporta in modo cooperativo, mentre un evento Windows si comporta in modo preemptive. Per ulteriori informazioni sugli eventi Windows, vedere Oggetti eventi (la pagina potrebbe essere in inglese).

Esempio

Descrizione

Per comprendere meglio la differenza tra la classe event e gli eventi Windows, considerare l'esempio seguente. Questo esempio consente all'utilità di pianificazione di creare al massimo due attività simultanee, quindi vengono chiamate due funzioni simili che utilizzano la classe event e un evento Windows di reimpostazione manuale. Ogni funzione crea innanzitutto diverse attività in attesa che un evento condiviso venga segnalato. Ogni funzione viene quindi restituita alle attività in esecuzione e segnala l'evento. Ogni funzione attende infine l'evento segnalato.

Codice

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

Commenti

Questo esempio produce l'output seguente:

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.

Poiché la classe event si comporta in modo cooperativo, l'utilità di pianificazione può riassegnare le risorse di elaborazione a un altro contesto mentre un evento è in attesa di passare allo stato segnalato. Pertanto, la versione che utilizza la classe event esegue più lavoro. Nella versione che utilizza gli eventi Windows, ogni attività in attesa deve passare allo stato segnalato prima che venga avviata l'attività successiva.

Per ulteriori informazioni sulle attività, vedere Parallelismo delle attività (runtime di concorrenza).

Vedere anche

Riferimenti

Oggetti sezione critica

Blocchi in lettura/scrittura ridotti (SRW)

Oggetti evento

Concetti

Strutture di dati di sincronizzazione