C# 多線程之同步輸出奇偶數

在論壇上見有人說有這麼個經典的面試題,我也來說說,^_^

此題涉及到:多線程,同步,排他

那前面順便講一下兩個排他應用的AutoResetEvent與ManualResetEvent的區別

AutoResetEvent:通知正在等待的線程已發生事件
ManualResetEvent :通知一個或多個正在等待的線程已發生事件


它們常用的三個事件有:
1)Set();  2)ReSet();   3)WaitOne();
字面上來說,一個是自動,一個是手動,其最跟本的區別是
一.AutoResetEvent的Set()只允許一個線程運行.也就是說AutoResetEvent的Set()方法,只會使一個線程得到運行,而使其它處於

WaitOne()狀態的線程自動爲ReSet()的無信號狀態.
二.而ManualResetEvent 的Set()則不會使處於WaitOne()狀態的線程自動爲ReSet()的無信號狀態.如果想其處於無信號狀態,必須手動調用ReSet()方法.

 //-----------------------------------------------------------------------

下面就直接給代碼了

using System;
using System.Collections.Generic;
using System.Threading;
using System.IO;


namespace ThreadTest
{
    #region main

    class Program
    {
        static void Main(string[] args)
        {
            TheadTest th = new TheadTest();
            th.Start();
            Console.ReadKey();
        }
    }
    /// <summary>
    /// 定義一個線程類
    /// </summary>
    class TheadTest
    {
        //定義一個Stream對象接收打開文件
        private FileStream st;
        //構造方法
        public TheadTest() 
        {
        }
        public void Start()
        {
            //定義兩個信號鎖
            AutoResetEvent ateA = new AutoResetEvent(false);
            AutoResetEvent ateB = new AutoResetEvent(false);
            //把信號鎖加入到List中
            List<AutoResetEvent> lst = new List<AutoResetEvent>();
            lst.Add(ateA);
            lst.Add(ateB);

            //定義帶參數的輸出偶數線程
            Thread thrEven = new Thread(new ParameterizedThreadStart(OutPutEven));
            //把兩個信號鎖傳入線程
            thrEven.Start(lst);

            //定義帶參數的輸出奇數線程
            Thread thrOdd = new Thread(new ParameterizedThreadStart(OutPutOdd));
            thrOdd.Start(lst);          
        }

        private void OutPutEven(object lst)
        {
            AutoResetEvent ateA = (lst as List<AutoResetEvent>)[0];
            AutoResetEvent ateB = (lst as List<AutoResetEvent>)[1];

            for (int i = 0; i < 100; i += 2)
            {
                //設置本線程爲無信號
                ateA.WaitOne();
                //輸出
                Console.WriteLine(i);
                //st = File.Open(@"C:\file.txt", FileMode.Open);      //用來測試同時訪問文件系統的
                //st.Close();
                ateB.Set();  //設置輸出奇數線程有信號
                //Thread.Sleep(500);
            }
        }
        private void OutPutOdd(object lst)
        {
            AutoResetEvent ateA = (lst as List<AutoResetEvent>)[0];
            AutoResetEvent ateB = (lst as List<AutoResetEvent>)[1];
            //設置偶數線程先輸出
            ateA.Set();
            for (int i = 1; i < 100; i += 2)
            {
                //設置本線程爲無信號
                ateB.WaitOne();
                Console.WriteLine(i);
                //st = File.Open(@"C:\file.txt", FileMode.Open);     //用來測試同時訪問文件系統的
                //st.Close();
                ateA.Set(); //設置輸出偶數線程有信號
                //Thread.Sleep(500);
            }
        }
    }
    #endregion main
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章