多綫程按順序輸出數字(信号量的使用)

一道經典的面試題:

使用兩個綫程按順序輸出1-100的數字,一個綫程輸出奇數,一個綫程輸出偶數。

看似很簡單,可是在綫程中用lock很輕鬆的實現鎖定綫程判斷變量奇偶性來控制打印和輸出,如果僅僅是這樣那麽就這道題就失去了考察的意義。

這道題實際上是在考察對綫程的控制,控制綫程同步的。

在C#中可以通過信號量這個東西來輕鬆控制綫程之間的同步,爲了更好的演示綫程的同步控制,示例中使用了三個綫程來演示。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace Test
{
    class Program
    {

        static void Main()
        {
            Console.WriteLine("Test");
            Test();
        }



        static void Test()
        {
            AutoResetEvent ateA = new AutoResetEvent(false);
            AutoResetEvent ateB = new AutoResetEvent(false);
            AutoResetEvent ateC = new AutoResetEvent(false);
            
            int i = 0;
            Thread th1 = new Thread((object ls) =>
            {
 
                while (i < 100)
                {
                    ateA.WaitOne();
                    if (i < 100)
                    {
                        Interlocked.Increment(ref i);
                        Console.WriteLine(i + "线程id" + Thread.CurrentThread.ManagedThreadId);
                    }
                    ateB.Set();
                }
                ateA.Close();
                Console.WriteLine("线程A关闭");
            });
            th1.Start();

            Thread th2 = new Thread((object ls) =>
            {
               
                while (i < 100)
                {
                    ateB.WaitOne();
                    if (i < 100)
                    {
                        Interlocked.Increment(ref i);
                        Console.WriteLine(i + "线程id" + Thread.CurrentThread.ManagedThreadId);
                       
                    }
                    ateC.Set();
                }
                ateB.Close();
                Console.WriteLine("线程B关闭");
            });
            th2.Start();

            Thread th3 = new Thread((object ls) =>
            {
               
                while (i < 100)
                {
                    ateC.WaitOne();
                    if (i < 100)
                    {
                        Interlocked.Increment(ref i);
                        Console.WriteLine(i + "线程id" + Thread.CurrentThread.ManagedThreadId);
                        ateA.Set();
                    }
                   
                }
                ateC.Set();
                Console.WriteLine("线程C关闭");

            });
            th3.Start();

            ateA.Set();

        }
    }
}

 

最終打印結果如下圖所示:

 

示例中使用的關鍵技術:

AutoResetEvent :通知正在等待的线程已发生事件

引申技術點:
ManualResetEvent :通知一个或多个正在等待的线程已发生事件
Semaphore  :https://www.cnblogs.com/yifengjianbai/p/5468449.html 可以參考該文檔的説明進行學習
posted @ 2019-03-13 16:39  Myisqq  阅读(160)  评论(0)    收藏  举报