C#多线程行为

Kab*_*uky 1 c# multithreading

我写了一个简单的多线程片段,让自己习惯了这个概念.

public void testThread(int arg1, ConsoleColor color)
    {
        for (int i = 0; i < 1000; i++)
        {
            Console.ForegroundColor = color;
            Console.WriteLine("Thread " + color.ToString() + " : " + i);
            Console.ResetColor();
            Thread.Sleep(arg1);
        }
    }

Thread t1 = new Thread(() => program.testThread(1000, ConsoleColor.Blue));
Thread t2 = new Thread(() => program.testThread(1000, ConsoleColor.Red));
t1.Start();
t2.Start();
t1.Join();
t2.Join();
Run Code Online (Sandbox Code Playgroud)

我在输出控制台窗口中看到的是

在此输入图像描述

我只是不明白为什么有时用红色装饰的线可能会变成白色或浅灰色(无论如何).你能帮助启发这个想法吗?

提前致谢.

Hei*_*nzi 7

您的代码块不是原子的.这意味着两个线程可以交织在一起.例:

   Thread 1 (Red)               Thread 2 (Blue)
--------------------------------------------------------------
                                 Set Color Blue
   Set Color Red         
                                 Print Text (printed in Red!)
   Print Text (printed in Red!)
Run Code Online (Sandbox Code Playgroud)

如果您希望线程的操作是原子的,即不间断的,则需要使用锁定:

private static readonly object myLock = new object();

public void testThread(int arg1, ConsoleColor color)
{
    for (int i = 0; i < 1000; i++)
    {
        lock (myLock) {
            Console.ForegroundColor = color;
            Console.WriteLine("Thread " + color.ToString() + " : " + i);
            Console.ResetColor();
        }
        Thread.Sleep(arg1);
    }
}
Run Code Online (Sandbox Code Playgroud)

锁的语句确保只有一个在线程的关键部分,在任何给定的时间:

   Thread 1 (Red)               Thread 2 (Blue)
--------------------------------------------------------------
                                 Enter critical section (lock)
   wait...                       Set Color Blue
                                 Print Text (printed in Red!)
                                 Reset Color
                                 Leave critical section
   Enter critical section (lock)
   ...
Run Code Online (Sandbox Code Playgroud)

  • 这种实现的唯一缺点是,如果创建了类a的2个实例,它们将不会相互锁定.由于控制台是静态的,因此最好使用静态对象来锁定. (2认同)

Bob*_*ale 5

因为

  • 线程1执行: Console.ForegroundColor = color;
  • 线程2执行: Console.ResetColor();
  • 线程1执行: Console.WriteLine("Thread " + color.ToString() + " : " + i);

您可以使用锁来防止这种情况发生.

private static readonly object lockObject=new object();

public void testThread(int arg1, ConsoleColor color)
{
    for (int i = 0; i < 1000; i++)
    {
        lock (lockObject) {
          Console.ForegroundColor = color;
          Console.WriteLine("Thread " + color.ToString() + " : " + i);
          Console.ResetColor();
        }
        Thread.Sleep(arg1);
    }
}

Thread t1 = new Thread(() => program.testThread(1000, ConsoleColor.Blue));
Thread t2 = new Thread(() => program.testThread(1000, ConsoleColor.Red));
t1.Start();
t2.Start();
t1.Join();
t2.Join();
Run Code Online (Sandbox Code Playgroud)