现在的位置: 首页 > 综合 > 正文

一个线程资源竞争的实例 及 防止

2012年11月07日 ⁄ 综合 ⁄ 共 2375字 ⁄ 字号 评论关闭

下面这段代码来自网上 ManualResetEvent和AutoResetEvent用法小试

对下面的代码有几个要说明的:

1   myThread.Join() 只对单一个线程,而且用在调用MyThread线程里,ManualResetEvent  可以等待多个线程 

2   myThread.Abort();线程在线这个方法时,并没有真正的中止线程 , 所以在后面还要加上Join
    myThread.Join();

3 请注意别外一些资源竞争的类或方法  mutex  lock  monitor  请注意他的同异!C#中运用Monitor类、Lock和Mutex类来同步多线程地执行

(下面如果把共享资源(nSubOne)的操作放到同一个函数里的话, 那么可以用Metux配合monitor 或者Lock 来实现)

4 另外的几个线程的函数 请参看.net 多线程初步(1)

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

namespace ManualAndAutoResetEventTest
{
    /// <summary>   
    /// 此类使用了ManualResetEvent,和AutoResetEvent   
    /// 功能一:ManualResetEvent用于,等待所有线程结束再执行   
    /// 功能二:AutoResetEvent用于线程间的同步   
    /// </summary>   
    class Program
    {
        #region === Filed ===
        //定义两个资源   
        static int nSubOne = 20;
        static int nSubTwo = 15;
        //设置手动重置信号量   
        //而ManualResetEvent 的Set()则不会使处于WaitOne()状态的线程自动为ReSet()的无信号状态.如果想其处于无信号状态,必须手动调用ReSet()方法.
        ManualResetEvent manA;
        ManualResetEvent manB;

        //设置自动重置信号量   
        // 下面设置为false 后 ThreadTwo()中要有ateA.set()不然程序一直阻塞
        //AutoResetEvent的Set()只允许一个线程运行.也就是说AutoResetEvent的Set()方法,只会使一个线程得到运行,而使其它处于WaitOne()状态的线程自动为ReSet()的无信号状态.
        AutoResetEvent ateA = new AutoResetEvent(false);//这个是设置初始状态 false表示waitone 而true 的话就是set 

        AutoResetEvent ateB = new AutoResetEvent(false );
        #endregion === Filed ===

        #region === Main Method ===

        static void Main(string[] args)
        {
            Program pg = new Program();
            pg.ThreadTest();
            Console.ReadLine();
        }

        #endregion === Main Method ===

        #region === Private Method ===
        void ThreadTest()
        {
            //初始化信号量   
            manA = new ManualResetEvent(false);//这个是设置初始状态 false表示waitone 而true 的话就是set 
            manB = new ManualResetEvent(false);
            //启动两个线程   
            Thread thdOne = new Thread(new ThreadStart(ThreadOne));
            thdOne.Start();
            Thread thdTwo = new Thread(new ThreadStart(ThreadTwo));
            thdTwo.Start();

            //等信号量manA,manB都释放了,才执行主线程   
            WaitHandle.WaitAll(new WaitHandle[2] { manA, manB });
            int n = 0;
            while (n < 10)
            {
                Console.WriteLine(n++);
                Thread.Sleep(50);
            }
        }
        void ThreadOne()
        {
            while (nSubOne > 0)
            {
                ateA.WaitOne();   //ateA保持等待   
                Console.WriteLine("T___1___:" + nSubOne--);
                ateB.Set(); //给ateB一个开始信号           
                Thread.Sleep(500);  //可以看出,线程一和线程2的Sleep时间并不一样,但是结果仍然是对的,           
                //这就是我们设置的同步信号量AutoResetEvent ateA,ateB的效果                  
            }
            manA.Set();  //给manA一个开始信号     
        }
        void ThreadTwo()
        {
            //*****************给A一个开始信号这个非常重要 , 如果下面这一句被注释掉了话,程序将一直在等待当中 
            //ateA.Set();    //给ateA一个开始信号           
            //while (nSubTwo > 0)  //可以在这试一下另一个线程操作,看是否主线程的确是等所有其它线程都执行完成才执行的.   
            //即看一下WaitHandle.WaitAll是否是真的有效了.   
            while (nSubOne > 0)
            {
                ateB.WaitOne();  //ateB保持等待   
                //Console.WriteLine("T___2___:" + nSubTwo--);   
                Console.WriteLine("T___2___:" + nSubOne++);
                ateA.Set();      //给ateA一个开始信号           
                Thread.Sleep(1);
            }
            manB.Set(); //给manB一个开始信号     
        }
        #endregion === Custom Method ===

    }
}

抱歉!评论已关闭.