Adloun

volatile n'est pas une synchronisation

Exercice · niveau 2 · informatique (MP2I/MPI), chapitre 22 — Concurrence et synchronisation

Énoncé

On entend souvent qu'il suffit de déclarer une variable partagée volatile. Le mettre à l'épreuve : quatre fils, incréments chacun.

Corrigé

Mesuré, sur quatre fils et incréments attendus :

déclarationessai 1essai 2essai 3
`int compteur`
`volatile int compteur`

Aucune différence. Le volatile n'a rien corrigé, et les deux colonnes sont indiscernables.

Ce que volatile dit vraiment : « ne garde pas cette variable dans un registre, relis-la en mémoire à chaque accès ». C'est une contrainte sur les optimisations du compilateur, faite pour les registres matériels dont la valeur change toute seule. Elle ne dit rien sur l'atomicité.

Or le défaut n'est pas là. compteur = compteur + 1 reste lire, ajouter, écrire : trois opérations, avec ou sans volatile. Un autre fil peut toujours s'intercaler entre la lecture et l'écriture, et l'incrément se perd exactement comme avant.

AttentionEt le type atomique de C11 ne suffit pas non plus, si on l'écrit mal

On pourrait croire que _Atomic int règle tout. Mesuré :

sur un `_Atomic int a`obtenu
`a = a + 1;`
`atomic_fetch_add` de

La première ligne est toujours fausse, et c'est instructif. Le type atomique rend atomique chaque lecture et chaque écriture — mais a = a + 1 en fait deux : une lecture atomique, puis une écriture atomique, avec un intervalle entre les deux. Seule une opération de lecture-modification-écriture indivisible, comme atomic_fetch_add, résout le problème.

La conclusion, et c'est la seule à retenir du chapitre : l'atomicité ne se déclare pas sur une variable, elle s'obtient sur une opération. Les deux moyens au programme sont le mutex et le sémaphore, et ils encadrent un morceau de code — pas une donnée. Tout le reste est une croyance.

Les autres exercices de ce chapitre Le cours du chapitre

Un blocage sur cet exercice ? Le tuteur d'Adloun guide par questions, sans donner la réponse.