Qu'est-ce que Section critique ?

Partie d'un programme manipulant des données partagées qui ne doit être exécutée que par un seul thread à la fois. On la protège par un verrou, par exemple, et on la garde aussi courte que possible.

Nom japonais: クリティカルセクション

« Section critique » apparaît dans 2 questions d'entraînement réparties sur 1 thèmes, dont Multicœur et synchronisation.

Domaine: Multicœur et synchronisation

Pourquoi les sections critiques existent

Même une instruction simple comme count++ se compile en une lecture, une modification et une écriture. Si deux threads l'exécutent en même temps, tous deux peuvent lire la même ancienne valeur et un incrément est perdu. Le code qui lit et met à jour des données partagées de cette façon est une section critique, et le bogue qui survient lorsque deux threads y entrent ensemble est une course aux données ou une condition de course. Une solution correcte doit garantir l'exclusion mutuelle, de sorte qu'un seul thread s'y trouve à la fois, tout en permettant aux threads en attente de progresser au lieu d'attendre indéfiniment.

Comment protéger une section critique

L'outil habituel est le verrou : un thread acquiert un mutex avant d'entrer et le libère à la sortie, et tout autre thread qui tente de l'acquérir se bloque ou tourne en boucle jusqu'à ce qu'il soit libre. Les verrous sont construits à partir d'instructions matérielles atomiques comme test-and-set, compare-and-swap ou load-linked/store-conditional, qui lisent et modifient un mot mémoire sans interférence. Un verrou tournant (spinlock) fait de l'attente active et convient aux sections très courtes sur systèmes multicœurs, tandis qu'un mutex qui endort le thread en attente convient aux attentes plus longues. Acquérir plusieurs verrous dans des ordres incohérents peut provoquer un interblocage (deadlock).

Désactiver les interruptions sur microcontrôleur

Sur un microcontrôleur monocœur, le code concurrent est souvent un gestionnaire d'interruption plutôt qu'un autre thread ; on protège donc couramment une section critique en désactivant les interruptions puis en les réactivant. Les interruptions qui arrivent entre-temps sont normalement mises en attente et traitées à la réactivation, mais de longues périodes de masquage retardent la gestion des temporisateurs et des communications et peuvent faire déborder les tampons. La section doit donc être aussi courte que possible. Sur un système multicœur, désactiver les interruptions sur un cœur ne suffit pas, car un autre cœur peut encore accéder aux données ; un verrou tournant ou une opération atomique est alors également nécessaire.

Garder les sections courtes et mémoire transactionnelle

Pendant qu'un thread détient un verrou, les autres attendent ; de longues sections critiques sérialisent donc un programme et annulent le bénéfice des cœurs supplémentaires. Les concepteurs les raccourcissent, divisent un verrou grossier en verrous plus fins pour des données indépendantes, ou utilisent des opérations atomiques sans verrou. La mémoire transactionnelle matérielle offre une autre voie : la section critique s'exécute de manière spéculative sous forme de transaction dont les écritures restent invisibles aux autres threads. Si aucun autre thread n'a touché aux mêmes données, elle est validée d'un seul coup ; en cas de conflit, elle est abandonnée, annulée, puis relancée ou bascule sur un verrou normal.

S'entraîner : questions sur Section critique

Quelle description de la section critique est correcte ?

  1. APartie du programme qui manipule des données partagées et ne doit être exécutée que par un seul thread à la fois
  2. BPartie du programme dont le temps d’exécution est le plus long
  3. CPartie exécutée uniquement en cas d’erreur
Afficher la réponse et l'explication

Réponse : A. Partie du programme qui manipule des données partagées et ne doit être exécutée que par un seul thread à la fois

Si plusieurs threads exécutent simultanément une partie qui lit et modifie une variable partagée, une course aux données survient. Une telle partie, qui ne doit être exécutée que par un seul thread à la fois, s’appelle section critique ; on la protège en prenant un verrou avant d’y entrer et en le libérant à la sortie. Plus la section critique est longue, plus les autres threads attendent ; la règle est de la garder aussi courte que possible.

Questions fréquentes

Quelle est la différence entre une section critique et un mutex ?

Une section critique est la région de code qui accède à des données partagées et ne doit pas s'exécuter de manière concurrente. Un mutex est l'un des mécanismes qui le garantissent, en ne laissant entrer dans la région que le thread qui le détient.

Pourquoi faut-il garder les sections critiques courtes ?

Les autres threads doivent attendre pendant qu'un thread s'y trouve, et sur microcontrôleur les interruptions peuvent être désactivées pendant ce temps. Des sections longues réduisent le parallélisme et retardent la réponse aux autres événements.

Désactiver les interruptions suffit-il à protéger une section critique ?

Sur un système monocœur où le seul concurrent est un gestionnaire d'interruption, c'est généralement suffisant. Sur un système multicœur, d'autres cœurs peuvent toujours s'exécuter ; un verrou ou une opération atomique est donc également nécessaire.

« Section critique » dans les explications

Questions mentionnant « Section critique » (2)

  1. Quelle description de la section critique est correcte ?
  2. Quel est le principe de la mémoire transactionnelle matérielle ?

Termes associés

Course aux données (data race) Mémoire transactionnelle Bascule (flip-flop) Acquisition-libération (acquire-release) Barrière mémoire Cohérence séquentielle Compare-and-swap Espionnage de bus (snooping) Faux partage (false sharing) Instruction atomique

Retour au glossaire