C# Language Éviter de lire et d'écrire des données simultanément


Exemple

Parfois, vous voulez que vos threads partagent des données simultanément. Lorsque cela se produit, il est important de connaître le code et de verrouiller toutes les pièces susceptibles de tomber en panne. Un exemple simple de comptage de deux threads est présenté ci-dessous.

Voici un code dangereux (incorrect):

using System.Threading;

class MainClass 
{    
    static int count { get; set; }

    static void Main() 
    {
        for (int i = 1; i <= 2; i++)
        {
            var thread = new Thread(ThreadMethod);
            thread.Start(i);
            Thread.Sleep(500);
        }
    }

    static void ThreadMethod(object threadNumber) 
    {
        while (true)
        {
            var temp = count;
            System.Console.WriteLine("Thread " + threadNumber + ": Reading the value of count.");
            Thread.Sleep(1000);
            count = temp + 1;
            System.Console.WriteLine("Thread " + threadNumber + ": Incrementing the value of count to:" + count);
            Thread.Sleep(1000);
        }
    }
}

Vous remarquerez, au lieu de compter 1,2,3,4,5 ... nous comptons 1,1,2,2,3 ...

Pour résoudre ce problème, nous devons verrouiller la valeur de count afin que plusieurs threads différents ne puissent pas lire et écrire en même temps. Avec l'ajout d'un verrou et d'une clé, nous pouvons empêcher les threads d'accéder aux données simultanément.

using System.Threading;

class MainClass
{

    static int count { get; set; } 
    static readonly object key = new object();

    static void Main()
    {
        for (int i = 1; i <= 2; i++)
        {
            var thread = new Thread(ThreadMethod);
            thread.Start(i);
            Thread.Sleep(500);
        }
    }

    static void ThreadMethod(object threadNumber)
    {
        while (true)
        {
            lock (key) 
            {
                var temp = count;
                System.Console.WriteLine("Thread " + threadNumber + ": Reading the value of count.");
                Thread.Sleep(1000);
                count = temp + 1;
                System.Console.WriteLine("Thread " + threadNumber + ": Incrementing the value of count to:" + count);
            }
            Thread.Sleep(1000);
        }
    }
}