在论坛上见有人说有这么个经典的面试题,我也来说说,^_^

此题涉及到:多线程,同步,排他

那前面顺便讲一下两个排他应用的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
}