Strutture di dati di sincronizzazione

Il runtime di concorrenza fornisce diverse strutture di dati che consentono di sincronizzare l'accesso ai dati condivisi da più thread. Queste strutture di dati sono utili quando si hanno dati condivisi che si modificano raramente. Un oggetto di sincronizzazione, ad esempio una sezione critica, causa l'attesa di altri thread fino a quando la risorsa condivisa non è disponibile. Pertanto, se si usa un oggetto di questo tipo per sincronizzare l'accesso ai dati usati di frequente, è possibile perdere la scalabilità nell'applicazione. La libreria PPL (Parallel Patterns Library) fornisce la classe concurrency::combinable , che consente di condividere una risorsa tra più thread o attività senza la necessità di sincronizzazione. Per altre informazioni sulla combinable classe , vedere Contenitori e oggetti paralleli.

Sezioni

In questo argomento vengono descritti in dettaglio i tipi di blocchi di messaggi asincroni seguenti:

critical_section

La classe concurrency::critical_section rappresenta un oggetto di esclusione reciproca cooperativo che restituisce ad altre attività anziché escluderle. Le sezioni critiche sono utili quando più thread richiedono l'accesso esclusivo in lettura e scrittura ai dati condivisi.

La critical_section classe non è reentrant. Il metodo concurrency::critical_section::lock genera un'eccezione di tipo concurrency::improper_lock se viene chiamato dal thread che possiede già il blocco.

Metodi e funzionalità

Nella tabella seguente vengono illustrati i metodi importanti definiti dalla critical_section classe .

metodo Descrizione
lock Acquisisce la sezione critica. Il contesto chiamante si blocca fino a quando non acquisisce il blocco.
try_lock Prova ad acquisire la sezione critica, ma non blocca.
unlock Rilascia la sezione critica.

[Torna all'inizio]

reader_writer_lock

La classe concurrency::reader_writer_lock fornisce operazioni di lettura/scrittura thread-safe ai dati condivisi. Usare blocchi reader/writer quando più thread richiedono l'accesso in lettura simultaneo a una risorsa condivisa, ma raramente scrivono in tale risorsa condivisa. Questa classe concede a un solo thread l'accesso in scrittura a un oggetto in qualsiasi momento.

La reader_writer_lock classe può offrire prestazioni migliori rispetto alla critical_section classe perché un critical_section oggetto acquisisce l'accesso esclusivo a una risorsa condivisa, che impedisce l'accesso in lettura simultaneo.

Analogamente alla critical_section classe , la reader_writer_lock classe rappresenta un oggetto di esclusione reciproca cooperativo che restituisce ad altre attività anziché eliminarle.

Quando un thread che deve scrivere in una risorsa condivisa acquisisce un blocco reader/writer, gli altri thread che devono accedere alla risorsa vengono bloccati fino a quando il writer non rilascia il blocco. La reader_writer_lock classe è un esempio di blocco delle preferenze di scrittura, ovvero un blocco che sblocca i writer in attesa prima di sbloccare i lettori in attesa.

Come la critical_section classe , la reader_writer_lock classe non è reentrant. I metodi concurrency::reader_writer_lock::lock e concurrency::reader_writer_lock::lock_read generano un'eccezione di tipo improper_lock se vengono chiamati da un thread che possiede già il blocco.

Nota

Poiché la reader_writer_lock classe non è reentrant, non è possibile aggiornare un blocco di sola lettura a un blocco reader/writer o effettuare il downgrade di un blocco reader/writer a un blocco di sola lettura. L'esecuzione di una di queste operazioni produce un comportamento non specificato.

Metodi e funzionalità

Nella tabella seguente vengono illustrati i metodi importanti definiti dalla reader_writer_lock classe .

metodo Descrizione
lock Acquisisce l'accesso in lettura/scrittura al blocco.
try_lock Prova ad acquisire l'accesso in lettura/scrittura al blocco, ma non blocca.
lock_read Acquisisce l'accesso in sola lettura al blocco.
try_lock_read Prova ad acquisire l'accesso di sola lettura al blocco, ma non blocca.
unlock Rilascia il blocco.

[Torna all'inizio]

scoped_lock e scoped_lock_read

Le critical_section classi e reader_writer_lock forniscono classi helper annidate che semplificano il modo in cui si lavora con oggetti di esclusione reciproca. Queste classi helper sono note come blocchi con ambito.

La critical_section classe contiene la classe concurrency::critical_section::scoped_lock . Il costruttore acquisisce l'accesso all'oggetto fornito critical_section . Il distruttore rilascia l'accesso a tale oggetto. La reader_writer_lock classe contiene la classe concurrency::reader_writer_lock::scoped_lock , simile critical_section::scoped_locka , ad eccezione del fatto che gestisce l'accesso in scrittura all'oggetto fornito reader_writer_lock . La reader_writer_lock classe contiene anche la classe concurrency::reader_writer_lock::scoped_lock_read . Questa classe gestisce l'accesso in lettura all'oggetto fornito reader_writer_lock .

I blocchi con ambito offrono diversi vantaggi quando si utilizzano critical_section oggetti e reader_writer_lock manualmente. In genere, si alloca un blocco con ambito nello stack. Un blocco con ambito rilascia automaticamente l'accesso all'oggetto di esclusione reciproca quando viene eliminato definitivamente; pertanto, non si sblocca manualmente l'oggetto sottostante. Ciò è utile quando una funzione contiene più return istruzioni. I blocchi con ambito consentono anche di scrivere codice indipendente dall'eccezione. Quando un'istruzione throw causa la rimozione dello stack, viene chiamato il distruttore per qualsiasi blocco con ambito attivo e pertanto l'oggetto di esclusione reciproca viene sempre rilasciato correttamente.

Nota

Quando si usano le critical_section::scoped_lockclassi , reader_writer_lock::scoped_locke reader_writer_lock::scoped_lock_read , non rilasciare manualmente l'accesso all'oggetto di esclusione reciproca sottostante. Questo può impostare il runtime in uno stato non valido.

evento

La classe di evento concurrency::event rappresenta un oggetto di sincronizzazione il cui stato può essere segnalato o non segnalato. A differenza degli oggetti di sincronizzazione, ad esempio sezioni critiche, il cui scopo è proteggere l'accesso ai dati condivisi, gli eventi sincronizzano il flusso di esecuzione.

La event classe è utile quando un'attività ha completato il lavoro per un'altra attività. Ad esempio, un'attività potrebbe segnalare a un'altra attività che contiene dati letti da una connessione di rete o da un file.

Metodi e funzionalità

La tabella seguente illustra diversi metodi importanti definiti dalla event classe .

metodo Descrizione
aspettare Attende che l'evento venga segnalato.
set Imposta l'evento sullo stato segnalato.
reset Imposta l'evento sullo stato non segnalato.
wait_for_multiple Attende la segnalazione di più eventi.

Esempio

Per un esempio che illustra come usare la event classe , vedere Confronto tra le strutture dei dati di sincronizzazione e l'API Windows.

[Torna all'inizio]

Confronto delle strutture di dati di sincronizzazione con l'API Windows
Confronta il comportamento delle strutture di dati di sincronizzazione con quelle fornite dall'API di Windows.

Runtime di concorrenza
Descrive il runtime di concorrenza che semplifica la programmazione parallela e contiene i collegamenti ad argomenti correlati.