Partager via


Structures de données de synchronisation

Le runtime d’accès concurrentiel fournit plusieurs structures de données qui vous permettent de synchroniser l’accès aux données partagées à partir de plusieurs threads. Ces structures de données sont utiles lorsque vous avez partagé des données que vous modifiez rarement. Un objet de synchronisation, par exemple, une section critique, entraîne l’attente d’autres threads jusqu’à ce que la ressource partagée soit disponible. Par conséquent, si vous utilisez un tel objet pour synchroniser l’accès aux données fréquemment utilisées, vous pouvez perdre l’extensibilité dans votre application. La bibliothèque de modèles parallèles (PPL) fournit la classe concurrency ::combinable , qui vous permet de partager une ressource entre plusieurs threads ou tâches sans avoir besoin de synchronisation. Pour plus d’informations sur la combinable classe, consultez Conteneurs et objets parallèles.

Sections

Cette rubrique décrit en détail les types de blocs de messages asynchrones suivants :

critical_section

La classe concurrency ::critical_section représente un objet d’exclusion mutuelle coopérative qui se traduit par d’autres tâches au lieu de les préempter. Les sections critiques sont utiles lorsque plusieurs threads nécessitent un accès exclusif en lecture et en écriture aux données partagées.

La critical_section classe n’est pas réentrante. La méthode concurrency ::critical_section ::lock lève une exception de type concurrency ::improper_lock si elle est appelée par le thread qui possède déjà le verrou.

Méthodes et fonctionnalités

Le tableau suivant présente les méthodes importantes définies par la critical_section classe.

Méthode Description
lock Acquiert la section critique. Le contexte appelant bloque jusqu’à ce qu’il acquiert le verrou.
try_lock Tente d’acquérir la section critique, mais ne bloque pas.
unlock Libère la section critique.

[Haut]

reader_writer_lock

La classe concurrency ::reader_writer_lock fournit des opérations de lecture/écriture thread-safe aux données partagées. Utilisez des verrous de lecteur/enregistreur lorsque plusieurs threads nécessitent un accès en lecture simultané à une ressource partagée, mais qu’ils écrivent rarement dans cette ressource partagée. Cette classe ne donne qu’un seul accès en écriture de thread à un objet à tout moment.

La reader_writer_lock classe peut fonctionner mieux que la critical_section classe, car un objet acquiert un critical_section accès exclusif à une ressource partagée, ce qui empêche l’accès en lecture simultané.

Comme la critical_section classe, la reader_writer_lock classe représente un objet d’exclusion mutuelle coopérative qui donne à d’autres tâches au lieu de les préempter.

Lorsqu’un thread qui doit écrire dans une ressource partagée acquiert un verrou lecteur/enregistreur, d’autres threads qui doivent également accéder à la ressource sont bloqués jusqu’à ce que l’enregistreur libère le verrou. La reader_writer_lock classe est un exemple de verrou de préférence d’écriture, qui est un verrou qui débloque les enregistreurs en attente avant de débloquer les lecteurs en attente.

Comme la critical_section classe, la reader_writer_lock classe n’est pas réentrante. Les méthodes concurrency ::reader_writer_lock ::lock et concurrency ::reader_writer_lock ::lock_read lèvent une exception de type improper_lock si elles sont appelées par un thread qui possède déjà le verrou.

Remarque

Étant donné que la reader_writer_lock classe n’est pas réentrante, vous ne pouvez pas mettre à niveau un verrou en lecture seule vers un verrou lecteur/enregistreur ou rétrograder un verrou lecteur/enregistreur vers un verrou en lecture seule. L’exécution de l’une de ces opérations produit un comportement non spécifié.

Méthodes et fonctionnalités

Le tableau suivant présente les méthodes importantes définies par la reader_writer_lock classe.

Méthode Description
lock Acquiert l’accès en lecture/écriture au verrou.
try_lock Tente d’acquérir l’accès en lecture/écriture au verrou, mais ne bloque pas.
lock_read Acquiert l’accès en lecture seule au verrou.
try_lock_read Tente d’acquérir un accès en lecture seule au verrou, mais ne bloque pas.
unlock Libère le verrou.

[Haut]

scoped_lock et scoped_lock_read

Les critical_section classes et reader_writer_lock les classes fournissent des classes d’assistance imbriquées qui simplifient la façon dont vous travaillez avec des objets d’exclusion mutuelle. Ces classes d’assistance sont appelées verrous délimités.

La critical_section classe contient la classe concurrency ::critical_section ::scoped_lock . Le constructeur acquiert l’accès à l’objet fourni critical_section ; le destructeur libère l’accès à cet objet. La reader_writer_lock classe contient la classe concurrency ::reader_writer_lock ::scoped_lock, qui ressemblecritical_section::scoped_lock, sauf qu’elle gère l’accès en écriture à l’objet fournireader_writer_lock. La reader_writer_lock classe contient également la classe concurrency ::reader_writer_lock ::scoped_lock_read . Cette classe gère l’accès en lecture à l’objet fourni reader_writer_lock .

Les verrous délimités offrent plusieurs avantages lorsque vous utilisez et reader_writer_lock utilisez critical_section des objets manuellement. En règle générale, vous allouez un verrou délimité sur la pile. Un verrou délimité libère automatiquement l’accès à son objet d’exclusion mutuelle lorsqu’il est détruit ; par conséquent, vous ne déverrouillez pas manuellement l’objet sous-jacent. Cela est utile lorsqu’une fonction contient plusieurs return instructions. Les verrous délimités peuvent également vous aider à écrire du code sans risque d’exception. Lorsqu’une throw instruction entraîne le déroulement de la pile, le destructeur pour tout verrou d’étendue active est appelé, et par conséquent, l’objet d’exclusion mutuelle est toujours libéré correctement.

Remarque

Lorsque vous utilisez les critical_section::scoped_lockclasses , reader_writer_lock::scoped_locket reader_writer_lock::scoped_lock_read que vous n’utilisez pas manuellement l’accès à l’objet d’exclusion mutuelle sous-jacent. Cela peut placer le runtime dans un état non valide.

événement

La classe concurrency ::event représente un objet de synchronisation dont l’état peut être signalé ou non signalé. Contrairement aux objets de synchronisation, tels que les sections critiques, dont l’objectif est de protéger l’accès aux données partagées, les événements synchronisent le flux d’exécution.

La event classe est utile lorsqu’une tâche a terminé le travail d’une autre tâche. Par exemple, une tâche peut signaler à une autre tâche qu’elle a lu des données à partir d’une connexion réseau ou d’un fichier.

Méthodes et fonctionnalités

Le tableau suivant présente plusieurs des méthodes importantes définies par la event classe.

Méthode Description
Attendre Attend que l’événement soit signalé.
set Définit l’événement à l’état signalé.
reset Définit l’événement à l’état non signalé.
wait_for_multiple Attend que plusieurs événements soient signalés.

Exemple

Pour obtenir un exemple montrant comment utiliser la event classe, consultez Comparaison des structures de données de synchronisation à l’API Windows.

[Haut]

Comparaison des structures de données de synchronisation avec l’API Windows
Compare le comportement des structures de données de synchronisation à celles fournies par l’API Windows.

Concurrency Runtime
Décrit le runtime d'accès concurrentiel, qui simplifie la programmation parallèle, et contient des liens vers les rubriques connexes.