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. |
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. |
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_lock
a , 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_lock
classi , reader_writer_lock::scoped_lock
e 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.
Sezioni correlate
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.