C#多线程行为

时间:2012-12-03 16:04:25

标签: 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();

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

enter image description here

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

提前致谢。

4 个答案:

答案 0 :(得分:7)

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

   Thread 1 (Red)               Thread 2 (Blue)
--------------------------------------------------------------
                                 Set Color Blue
   Set Color Red         
                                 Print Text (printed in Red!)
   Print Text (printed in Red!)

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

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);
    }
}

lock statement确保在任何给定时间critical section中只包含一个线程:

   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)
   ...

答案 1 :(得分: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();

答案 2 :(得分:3)

您正在调用Console.ResetColor();,将颜色设置回默认值(灰色)。因为你有两个线程同时写入控制台,有时一个线程重置之后另一个线程设置它的颜色,但之前另一个线程打印。

您可以使用thread synchronization解决此问题。

答案 3 :(得分:1)

您需要锁定设置控制台颜色的段,直到您打印文本为止。

在打印文本之前,线程可能会中断并重置颜色。

像这样更改你的代码:

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

var lockObj = new object();
Thread t1 = new Thread(() => program.testThread(1000, ConsoleColor.Blue, lockObj));
Thread t2 = new Thread(() => program.testThread(1000, ConsoleColor.Red, lockObj));