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 de plusieurs threads. Ces structures de données sont utiles lorsque vous avez des données partagées que vous modifiez rarement. Un objet de synchronisation, par exemple une section critique, fait en sorte que d'autres threads attendent que la ressource partagée soit disponible. Par conséquent, si vous utilisez un tel objet pour synchroniser l'accès à des données qui sont utilisées fréquemment, vous pouvez perdre la montée en charge dans votre application. La Bibliothèque de modèles parallèles fournit la classe Concurrency::combinable, qui vous permet de partager une ressource entre plusieurs threads ou tâches sans avoir recours à la synchronisation. Pour plus d'informations sur la classe combinable, consultez Conteneurs et objets parallèles.

Sections

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

  • critical_section

  • reader_writer_lock

  • scoped_lock et scoped_lock_read

  • event

critical_section

La classe Concurrency::critical_section représente un objet d'exclusion mutuelle coopératif qui cède à d'autres tâches au lieu de les préempter. Les sections critiques sont utiles lorsque plusieurs threads requièrent un accès en lecture et en écriture exclusif aux données partagées.

La classe critical_section est non 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 détient déjà le verrou.

Méthodes et fonctionnalités

Le tableau suivant répertorie les méthodes importantes définies par la classe critical_section.

Méthode

Description

lock

Acquiert la section critique. Le contexte appelant bloque jusqu'à ce qu'il acquière le verrou.

try_lock

Essaie d'acquérir la section critique, mais ne bloque pas.

unlock

Libère la section critique.

[retour en haut]

reader_writer_lock

La classe Concurrency::reader_writer_lock fournit des opérations en lecture/écriture thread-safe aux données partagées. Utilisez des verrous de lecteur/writer lorsque plusieurs threads requièrent un accès en lecture simultané à une ressource partagée mais écrivent rarement dans cette ressource partagée. Cette classe accorde un accès en écriture à un objet à un seul thread à tout moment.

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

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

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

Comme la classe critical_section, la classe reader_writer_lock est non 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 détient déjà le verrou.

Notes

Étant donné que la classe reader_writer_lock est non réentrante, il n'est pas possible de mettre à niveau un verrou en lecture seule en un verrou lecture/écriture, ni de rétrograder un verrou lecture/écriture en un verrou en lecture seule. L'exécution de l'une ou l'autre de ces opérations provoque un comportement inattendu.

Méthodes et fonctionnalités

Le tableau suivant répertorie les méthodes importantes définies par la classe reader_writer_lock.

Méthode

Description

lock

Acquiert l'accès en lecture/écriture au verrou.

try_lock

Essaie 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

Essaie d'acquérir l'accès en lecture seule au verrou, mais ne bloque pas.

unlock

Libère le verrou.

[retour en haut]

scoped_lock et scoped_lock_read

Les classes reader_writer_lock et critical_section fournissent des classes d'assistance imbriquées qui simplifient la façon dont vous utilisez les objets d'exclusion mutuelle. Ces classes d'assistance portent le nom de verrous à portée limitée.

La classe critical_section contient la classe Concurrency::critical_section::scoped_lock. Le constructeur acquiert l'accès à l'objet critical_section fourni ; le destructeur libère l'accès à cet objet. La classe reader_writer_lock contient la classe Concurrency::reader_writer_lock::scoped_lock, qui s'apparente à critical_section::scoped_lock mais gère l'accès en écriture à l'objet reader_writer_lock fourni. La classe reader_writer_lock contient également la classe Concurrency::reader_writer_lock::scoped_lock_read. Cette classe gère l'accès en lecture à l'objet reader_writer_lock fourni.

Les verrous à portée limitée procurent plusieurs avantages lorsque vous travaillez manuellement avec des objets critical_section et reader_writer_lock. En général, vous allouez un verrou à portée limitée sur la pile. Un verrou à portée limitée libère automatiquement l'accès à son objet d'exclusion mutuelle lorsqu'il est détruit ; par conséquent, vous ne déverrouillez pas l'objet sous-jacent manuellement. Ceci est utile lorsqu'une fonction contient plusieurs instructions return. Les verrous à portée limitée peuvent également vous aider à écrire du code sécurisé du point de vue des exceptions. Lorsqu'une instruction throw provoque le déroulement de la pile, le destructeur de tout verrou à portée limitée actif est appelé. Par conséquent, l'objet d'exclusion mutuelle est toujours libéré correctement.

Notes

Lorsque vous utilisez les classes critical_section::scoped_lock, reader_writer_lock::scoped_lock et reader_writer_lock::scoped_lock_read, ne libérez pas manuellement l'accès à l'objet d'exclusion mutuelle sous-jacent. Cela peut mettre le runtime dans un état non valide.

event

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 classe event est utile lorsqu'une tâche a terminé du travail pour 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 répertorie plusieurs des méthodes importantes définies par la classe event.

Méthode

Description

wait

Attend que l'événement soit signalé.

set

Place l'événement à l'état signalé.

reset

Place l'événement à l'état non signalé.

wait_for_multiple

Attend que plusieurs événements soient signalés.

Exemple

Pour obtenir un exemple qui illustre l'utilisation de la classe event, consultez Comparaison de structures de données de synchronisation avec l'API Windows.

[retour en haut]

Rubriques connexes