Les valeurs mises en cache sur les threads peuvent-elles ignorer les modifications apportées sur d'autres threads ?
Cette question se concentre sur la question de savoir si un thread C# peut mettre en cache une valeur et ignorer modifications ultérieures apportées à cette valeur sur différents threads. Malgré les connaissances communes sur les conditions de concurrence, l'atomicité et l'utilisation de verrous, l'enquête cible spécifiquement les scénarios dans lesquels le runtime .NET pourrait potentiellement éliminer les problèmes de mémoire volatile.
Certaines sources affirment que dans le code suivant, la lecture le thread peut mettre en cache la valeur initiale de la variable bool "en s'arrêtant" et ne jamais détecter sa modification, conduisant potentiellement à une boucle infinie :
class BackgroundTaskDemo { private bool stopping = false; static void Main() { BackgroundTaskDemo demo = new BackgroundTaskDemo(); new Thread(demo.DoWork).Start(); Thread.Sleep(5000); demo.stopping = true; } static void DoWork() { while (!stopping) { // Do something here } } }
Cependant, la validité de cette affirmation est contesté. Les critiques se demandent si le runtime .NET ignorerait véritablement les modifications apportées aux valeurs de la mémoire, comme cela est allégué. Ils soulignent que le code donné fonctionne « presque certainement », ce qui implique que la réclamation n'est pas fondée.
Le nœud du problème est que le comportement décrit dans la réclamation n'est pas garanti par la spécification .NET. Bien que cela puisse fonctionner dans la plupart des cas, il n’est pas garanti que cela fonctionnera dans toutes les circonstances. Les experts dans le domaine des modèles de mémoire mettent en garde contre le fait de se fier à des résultats aussi peu fiables.
De plus, un contre-exemple vérifiable a été présenté, démontrant un scénario spécifique dans lequel le code échoue comme prévu. Dans le code révisé suivant, "stopping" est déclaré volatil pour corriger le problème :
using System.Threading; using System; static class BackgroundTaskDemo { // make this volatile to fix it private static bool stopping = false; static void Main() { new Thread(DoWork).Start(); Thread.Sleep(5000); stopping = true; Console.WriteLine("Main exit"); Console.ReadLine(); } static void DoWork() { int i = 0; while (!stopping) { i++; } Console.WriteLine("DoWork exit " + i); } }
Lorsqu'il est exécuté en mode "release" sans le mot-clé volatile, le code entre dans une boucle infinie et continue de s'exécuter indéfiniment, même après que "stopping" ait été défini sur true. Cependant, l'ajout de "volatile" à la variable "stopping" résout le problème, permettant à la boucle de se terminer comme prévu.
La conclusion est que même si le code peut souvent sembler fonctionner, il ne peut pas être garanti qu'il le fera. de manière cohérente. Pour un code multithread robuste et fiable, l'utilisation de verrous ou du mot clé volatile est fortement conseillée.
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!