首頁  >  文章  >  後端開發  >  C# 執行緒同步與執行緒池 淺析

C# 執行緒同步與執行緒池 淺析

黄舟
黄舟原創
2017-03-03 13:34:491497瀏覽

 C# 執行緒同步與執行緒池

 範例很簡單,準備5個執行緒,每個執行緒同時向控制台輸出數字,然後觀察輸出結果。

程式碼說明:

////執行緒清單

private static List<Thread> _threadList;
 
 
        static voidMain(string[] args)
        {
            Program._threadList= new List<Thread>();
            ////附加5个线程
            for (inti = 0; i < 5; i++)
            {
                Program.AppendThread();
            }
 
            ////开始执行所有测试线程
            Program.ExecuteThread();
 
            ////按任意键退出
            Console.ReadLine();
        }
 
        /// <summary>
        /// 将新的测试线程附加到测试线程列表,线程执行逻辑就是输出10个数字
/// 注意初始化的时候设置为后台线程了,这样可以保证主线程退出的时候其他线/// 程自动退出
        /// </summary>
        public staticvoid AppendThread()
        {
            Program._threadList.Add(newThread(new ThreadStart(
                () =>
                {
                   for (int i = 0; i < 10; i++)
                   {
                       Console.WriteLine(i);
                   }
                })){ IsBackground = true });
        }
 
        /// <summary>
        /// 开始执行所有测试线程
        /// </summary>
        public staticvoid ExecuteThread()
        {
            foreach(Thread t in _threadList)
            {
                t.Start();
            }
        }

觀察執行結果,我們可以看到結果如下:

根據結果(數字的輸出是不規則的)可知,執行緒之間發生了乾擾。策略就是,加一個同步成員來進行線程同步:           

   /// <summary>
        /// 多线程同步的对象
        /// </summary>
        private static object _syncObj = new object();
另外,在线程执行的地方加锁:
Program._threadList.Add(newThread(new ThreadStart(
                () =>
                {
                    lock (_syncObj)
                    {
                        for (int i = 0; i < 10;i++)
                        {
                            Console.WriteLine(i);
                        }
                    }
 
                })) { IsBackground = true });

觀察結果:

可以看到透過Lock關鍵字,對一個多執行緒同步的變數加鎖的確可以使得執行緒同步。

現在看一下第二種方式:

使用monitor關鍵字進行同步,程式碼:

Monitor.Enter(_syncObj);
                   try
                   {
                       for (int i = 0; i < 10; i++)
                       {
                            Console.WriteLine(i);
                       }
                   }
                   finally {
                       Monitor.Exit(_syncObj);
                   }

檢視結果,會發現執行緒已經同步了。

第三種方式:

現在讓我們重構一下程式碼,新建一個ThreadManager的類,把類別的職責都搬進去:

class ThreadManager
    {
        /// <summary>
        /// 线程列表
        /// </summary>
        private staticList<Thread> _threadList;
 
        staticThreadManager()
        {
           _threadList = new List<Thread>();
        }
 
        /// <summary>
        /// 附加新线程
        /// </summary>
        public staticvoid AppendThread()
        {
            ThreadManager._threadList.Add(newThread(new ThreadStart(
                () =>
                {
                   for (int i = 0; i < 10; i++)
                   {
                       Console.WriteLine(i);
                   }
 
                })){ IsBackground = true });
        }
 
        /// <summary>
        /// 开始执行所有线程
        /// </summary>
        public staticvoid ExecuteThread()
        {
            foreach(Thread t in _threadList)
            {
                t.Start();
            }
        }
    }

Main函數呼叫的程式碼做對應的改變:

static voidMain(string[] args)
        {
            ////附加5个线程
            for (int i = 0; i < 5; i++)
            {
                ThreadManager.AppendThread();
            }
 
            ////开始测试
            ThreadManager.ExecuteThread();
 
            ////按任意键继续
            Console.ReadLine();
        }

由於沒有對執行緒同步做任何處理,結果肯定可以猜到,執行緒是不同步的:

 現在對ThreadManager這個類別加上特性:[Synchronization],再運行之,發現線程同步了,這就是線程同步的第四種方案,用起來很簡單,但是首先它要求執行邏輯都放在一個類別中,由於它可以確保這個類別中的所有方法都是線程安全的,因此它的性能相對低效

執行緒同步還有方法嗎?答案是肯定的,那就是第四種方法—線程池。

現在來看看如何用執行緒池來實作:

  static void Main(string[]args)
        {
/////定义一个waitCallback对象,并定义它的行为,就是向控制台输出十个数字同时可以传递/////一个参数(这个参数是可选的)
                       WaitCallback work = new WaitCallback((o)=>
            {
                for(int i = 0; i < 10; i++)
                {
                   Console.WriteLine(i);
                }
            });
 
            ////执行5次
            for (inti = 0; i < 5; i++)
            {
/////如果这里需要传递参数,可以调用另一个重载方法
                ThreadPool.QueueUserWorkItem(work);
            }
 
            ////按任意键继续
            Console.ReadLine();
        }

這樣就完成了剛剛的邏輯嗎?是的,運行之後我們可以看到結果,執行緒是同步的。

多執行緒還帶來了哪些好處?

  •   執行緒池減少了執行緒建立、開始和停止的次數,從而提高了效率;

  •   使用執行緒池,能夠使我們將注意力放到業務邏輯上而不是多執行緒架構上(然而在某些情況應優先使用手動執行緒管理)

  • #  如果需要前台執行緒或設定優先級,或執行緒池中的線程總是後台線程,且他的優先權是預設的;

  •   如果需要一個有固定標識的執行緒便於退出,掛起或透過名字發現它。

 

 以上是C# 執行緒同步與執行緒池  淺析的內容,更多相關內容請關注PHP中文網(www.php.cn)!


#
陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn