线程同步打印字符串

时间:2015-02-16 13:33:51

标签: c# multithreading synchronization

我写了一个小程序,打印“x”,然后是“+”,然后是“x”,依此类推。 我的想法是让它在两个线程中运行,以便第一个线程打印“x”,第二个线程打印“+”。输出如下所示: “x” - >线程号1 “+” - >线程号2 “x” - >主题1 enter code here “+” - >线程号2 等等..

我写的内容似乎工作正常,但在我看来它是写的 非常老套的方式:

 public class Example
 {
    private static int count = 10;
    private static int i = 0;
    private static bool isOneActive = false;


  private static void Run1(object o)
  {
      string s = o as string;

      while(true)
      {
          if (!isOneActive)
          {
              Console.WriteLine("Hello from thread number: " +   
                      Thread.CurrentThread.ManagedThreadId + " -> " + s);
              isOneActive = true;
              if (i++ > count) break;
          }
      }
  }

  private static void Run2(object o)
  {
      string s = o as string;

      while(true)
      {
          if (isOneActive)
          {
              Console.WriteLine("Hello from thread number: " + 
                Thread.CurrentThread.ManagedThreadId + " -> " + s);
              isOneActive = false;
              if (i++ > count) break;
          }
      }
  }

  static void Main()
  {
      Thread t1 = new Thread(Run1);
      Thread t2 = new Thread(Run2);
      t1.Start("x");
      t2.Start("+");
  }

我知道现在.NET有许多用于线程同步的工具,例如ManualResetEvent类和Task库。那么我们如何使用ManualResetEvent类编写相同的程序呢?它有可能吗?

2 个答案:

答案 0 :(得分:4)

您的代码不仅仅是老式的,效率非常低。它无缘无故地旋转,只能等待;这应称为Busy wait应该尽可能避免。

更好的方法是使用评论中提到的Waithandles。

一个简单的实现,代码变化很小,如下所示。

public class Example
{
    private static int count = 10;
    private static int i = 0;
    private static AutoResetEvent firstEvent = new AutoResetEvent(true);
    private static AutoResetEvent secondEvent = new AutoResetEvent(false);


    private static void Run1(object o)
    {
        string s = o as string;

        while (true)
        {
            firstEvent.WaitOne();
            Console.WriteLine("Hello from thread number: " + Thread.CurrentThread.ManagedThreadId + " -> " + s);
            secondEvent.Set();
            if (Interlocked.Increment(ref i) > count)
                break;
        }
    }

    private static void Run2(object o)
    {
        string s = o as string;

        while (true)
        {
            secondEvent.WaitOne();
            Console.WriteLine("Hello from thread number: " + Thread.CurrentThread.ManagedThreadId + " -> " + s);
            firstEvent.Set();
            if (Interlocked.Increment(ref i) > count)
                break;
        }
    }

    static void Main()
    {
        Thread t1 = new Thread(Run1);
        Thread t2 = new Thread(Run2);
        t1.Start("x");
        t2.Start("+");
    }
}

请注意firstEvent是在初始状态标志设置为true的情况下实例化的,这意味着第一个线程最初不会等待。

答案 1 :(得分:3)

考虑这个例子(fiddle):

    static void Main(string[] args)
    {
        var console = new object();
        int i = 0;
        Task.Run(() =>
        {
            lock (console)
                while (i++ < 10)
                {
                    Console.Write(i);
                    Monitor.Pulse(console);
                    Monitor.Wait(console);
                }
        });
        Task.Run(() =>
        {
            lock (console)
                while (i < 10)
                {
                    Console.Write('+');
                    Monitor.Pulse(console);
                    Monitor.Wait(console);
                }
        });
        Console.ReadLine(); // Task.WaitAll might be better, remove for fiddle
    }