« Salut Amigo ! »

« Salut, Élie ! »

« Je veux vous parler du modificateur volatil. Savez-vous ce que c'est ? »

"Quelque chose à voir avec les fils. Je ne me souviens pas exactement."

"Alors écoutez. Voici quelques détails techniques pour vous :"

"Un ordinateur possède deux types de mémoire : la mémoire globale (ordinaire) et la mémoire intégrée au processeur. La mémoire intégrée du processeur est divisée en registres, un cache de premier niveau (L1), un cache de deuxième niveau (L2) et troisième niveau (L3)."

"Ces types de mémoire ont des vitesses différentes. La mémoire la plus rapide et la plus petite sont les registres, puis le cache du processeur (L1, L2, L3) et enfin la mémoire globale (la plus lente)."

"La mémoire globale et le cache du processeur fonctionnent à des vitesses très différentes, de sorte que la machine Java permet à chaque thread de stocker les variables les plus fréquemment utilisées dans la mémoire des threads locaux (dans le cache du processeur)."

"Ce processus peut-il être contrôlé d'une manière ou d'une autre?"

"Pas vraiment. Tout le travail est fait par la machine Java. C'est très intelligent quand il s'agit d'optimiser les performances."

"Mais voici pourquoi je vous dis cela. Il y a un petit problème. Lorsque deux threads travaillent avec la même variable, chacun peut stocker une copie dans son propre cache local. Et puis un thread peut changer la variable, mais le second peut ne pas voir le changement, car il fonctionne toujours avec sa propre copie de la variable."

"Eh bien, que peut-on faire alors ?"

"Les créateurs de Java ont fourni un mot-clé spécial pour cette situation : volatile. Si une variable est accessible à partir de différents threads, vous devez la marquer avec le modificateur volatile, afin que la machine Java ne la mette pas dans le cache. regards:"

public volatile int count = 0;

"Oh, je m'en souviens. Tu l'as déjà mentionné. Je le sais déjà."

"Bien sûr que oui. Mais tu ne t'en souviens que quand je te l'ai dit."

"Euh, eh bien, j'ai un peu oublié."

"La répétition est la mère de l'apprentissage !"

"Voici quelques faits nouveaux sur le modificateur volatil. Le modificateur volatil garantit uniquement que la variable sera lue et écrite en toute sécurité. Il ne garantit pas qu'elle sera modifiée en toute sécurité."

"Quelle est la différence?"

"Regardez comment la variable est modifiée :"

Code Que se passe-t-il vraiment : Description
count++
register = count;

register = register+1;

count = register;
Étape 1.
La valeur du nombre de variables est copiée de la mémoire globale vers un registre du processeur.

Étape 2.
À l'intérieur du processeur, la variable de registre est incrémentée de 1.

Étape 3.
La valeur de la variable est copiée du processeur vers la mémoire globale.

"Wow ! Donc, toutes les variables ne sont modifiées que dans le processeur ?"

"Ouais."

"Et les valeurs sont copiées dans les deux sens : de la mémoire au processeur et vice-versa ?"

"Ouais."

"Le modificateur volatil garantit que lorsque la variable count est accessible, elle sera lue à partir de la mémoire (étape 1). Et si un thread veut attribuer une nouvelle valeur, elle sera définitivement dans la mémoire globale (étape 3)."

"Mais la machine Java ne garantit pas qu'il n'y aura pas de changement de thread entre les étapes 1 et 3."

"Alors, incrémenter la variable de 1 correspond en fait à trois opérations ?"

"Oui."

"Et si deux threads veulent simultanément exécuter count++, alors ils pourraient interférer l'un avec l'autre ?"

"Oui, regarde ça :"

Sujet 1 Fil 2 Résultat
register1 = count;
register1++;
count = register1;
register2 = count;
register2++;
count = register2;
register1 = count;
register2 = count;
register2++;
count = register2;
register1++;
count = register1;

« Donc, vous pouvez accéder à la variable, mais la modifier est toujours risqué ? »

"Eh bien, vous pouvez le changer, faites juste attention ☺"

"Comment?"

" Le synchronisé  est notre meilleur ami."

"Je vois."