Maison >développement back-end >C++ >Un thread C# peut-il ignorer les modifications de valeur provenant d'autres threads ?
Cette question explore une anomalie potentielle dans le comportement du thread C#, sans rapport avec les conditions de concurrence ou le besoin de verrous. Plus précisément, la préoccupation est de savoir si un thread peut mettre en cache une valeur et ignorer les modifications apportées à cette valeur sur d'autres threads, ce qui pourrait entraîner un comportement inattendu.
Le runtime NET, qui gère la mémoire, est censé atténuer ce problème. Cependant, certains ouvrages affirment le contraire, affirmant que certaines structures de code, comme les suivantes, peuvent conduire à des boucles infinies :
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 } } }
Selon les articles référencés (http://www.yoda.arachsys.com/ csharp/threads/volatility.shtml , http://softwareengineering.stackexchange.com/questions/104757/is-a-string-property-itself-threadsafe), le thread de lecture peut mettre en cache la valeur initiale de la variable d'arrêt, rendant ainsi invisibles toutes les mises à jour ultérieures et provoquant le thread à s'exécute indéfiniment.
Cependant, les experts en modélisation de mémoire insistent sur le fait qu'un tel comportement n'est pas garanti par la spécification C#. Bien que le code fourni puisse généralement fonctionner correctement, il repose sur des optimisations spécifiques à la plate-forme et au compilateur plutôt que sur une sémantique concrète du langage.
Pour illustrer davantage le problème, considérons le code modifié suivant :
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); } }
Avec cette modification, le code affiche de manière prévisible « Sortie principale », mais la méthode DoWork continue de s'exécuter indéfiniment. Ce contre-exemple démontre que, malgré les soupçons initiaux, le runtime C# ne garantit pas toujours la cohérence des mises à jour des valeurs entre les threads.
Pour résoudre cette ambiguïté, le mot-clé volatile peut être appliqué à la variable d'arrêt. Le modificateur volatile applique l'accès atomique à la variable, empêchant les valeurs mises en cache de masquer les mises à jour réelles.
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!