码迷,mamicode.com
首页 > 其他好文 > 详细

信号量 <第六篇>

时间:2014-08-29 12:28:57      阅读:409      评论:0      收藏:0      [点我收藏+]

标签:blog   http   strong   ar   art   div   代码   log   sp   

一、ManualResetEvent

      该对象有两种信号量状态True和False。构造函数设置初始状态。

  • WaitOne:该方法用于阻塞线程,默认是无限期的阻塞,支持超时阻塞,如果超时就放弃阻塞,这样也就避免了无限期等待的尴尬;
  • Set:手动修改信号量为True,也就是恢复线程执行;
  • ReSet:重置状态;
bubuko.com,布布扣
    class Program
    {
        public static void Main()
        {
            Thread t = new Thread(Run);
            t.Name = "辅助线程";
            t.Start();

            Console.WriteLine("当前时间:{0}  {1}准备执行!", DateTime.Now.TimeOfDay, t.Name);
            //手动修改信号量为True,也就是恢复一个等待线程执行。
            mr.Set();

            Console.ReadKey();
        }

        //一开始设置为false才会等待收到信号才执行
        static ManualResetEvent mr = new ManualResetEvent(true);

        static void Run()
        {
            //线程开始执行时待命,收到信号才动身
            mr.WaitOne();
            Console.WriteLine("\n当前时间:{0}  {1}正式执行!", DateTime.Now.TimeOfDay, Thread.CurrentThread.Name);

            //我想让辅助线程暂停3秒
            mr.WaitOne(3000);
            Console.WriteLine("\n当前时间:{0}  {1}暂停3秒,但是无效!", DateTime.Now.TimeOfDay, Thread.CurrentThread.Name);

            //我想让辅助线程暂停
            mr.Reset();
            Console.WriteLine("\n当前时间:{0}  {1}还是无效!", DateTime.Now.TimeOfDay, Thread.CurrentThread.Name);
        }
    }
bubuko.com,布布扣

  输出如下:

  bubuko.com,布布扣

   Reset()的意思其实是重置,重置后才又能再WaitOne();

bubuko.com,布布扣
    class Program
    {
        public static void Main()
        {
            Thread t = new Thread(Run);
            t.Name = "辅助线程";
            t.Start();

            Console.WriteLine("当前时间:{0}  {1}准备执行!", DateTime.Now.TimeOfDay, t.Name);
            //手动修改信号量为True,也就是恢复一个等待线程执行。
            mr.Set();


            Thread.Sleep(10000);
            mr.Set();

            Console.ReadKey();
        }

        //一开始设置为false才会等待收到信号才执行
        static ManualResetEvent mr = new ManualResetEvent(false);

        static void Run()
        {
            //线程开始执行时待命,收到信号才动身
            mr.WaitOne();
            Console.WriteLine("\n当前时间:{0}  {1}正式执行!", DateTime.Now.TimeOfDay, Thread.CurrentThread.Name);

            //重置后停止才有效
            mr.Reset();
            //我想让辅助线程暂停3秒
            mr.WaitOne(3000);
            Console.WriteLine("\n当前时间:{0}  {1}暂停3秒,这回有效了!", DateTime.Now.TimeOfDay, Thread.CurrentThread.Name);

            //重置后停止才有效
            mr.Reset();
            //我想让辅助线程暂停,10后由主线程再次唤醒
            mr.WaitOne();
            Console.WriteLine("\n当前时间:{0}  {1}暂停,但会被主线程再次唤醒,这回有效了!", DateTime.Now.TimeOfDay, Thread.CurrentThread.Name    );
        }
    }
bubuko.com,布布扣

  输出如下:

   bubuko.com,布布扣

二、AutoResetEvent

  AutoResetEvent与ManualResetEvent的区别在于AutoResetEvent 的WaitOne会改变信号量的值。

  比如说初始信号量为True,如果WaitOne超时信号量将自动变为False,而ManualResetEvent则不会。

bubuko.com,布布扣
    class Program
    {
        public static void Main()
        {
            Thread t = new Thread(Run);
            t.Name = "辅助线程";
            t.Start();

            Console.WriteLine("当前时间:{0}  {1}准备执行!", DateTime.Now.TimeOfDay, t.Name);

            Console.ReadKey();
        }

        static AutoResetEvent ar = new AutoResetEvent(true);

        static void Run()
        {
            var state = ar.WaitOne(1000);
            Console.WriteLine("当前的信号量状态:{0}", state);

            state = ar.WaitOne(1000);
            Console.WriteLine("再次WaitOne后现在的状态是:{0}", state);
        }
    }
bubuko.com,布布扣

  输出如下:

  bubuko.com,布布扣

  假如要实现上面ManualResetEvent同样的效果,Run方法就不用手动Reset()了:

bubuko.com,布布扣
    static void Run()
    {
        //线程开始执行时待命,收到信号才动身
        mr.WaitOne();
        Console.WriteLine("\n当前时间:{0}  {1}正式执行!", DateTime.Now.TimeOfDay, Thread.CurrentThread.Name);

        //我想让辅助线程暂停3秒
        mr.WaitOne(3000);
        Console.WriteLine("\n当前时间:{0}  {1}暂停3秒,这回有效了!", DateTime.Now.TimeOfDay, Thread.CurrentThread.Name);

        //我想让辅助线程暂停,10后由主线程再次唤醒
        mr.WaitOne();
        Console.WriteLine("\n当前时间:{0}  {1}暂停,但会被主线程再次唤醒,这回有效了!", DateTime.Now.TimeOfDay, Thread.CurrentThread.Name);
    }
bubuko.com,布布扣

  少了手动Reset()代码。

三、Semaphore

  用于控制线程的访问数量,默认的构造函数为initialCount和maximumCount,表示默认设置的信号量个数和最大信号量个数。当你WaitOne的时候,信号量自减,当Release的时候,信号量自增,然而当信号量为0的时候,后续的线程就不能拿到WaitOne了,所以必须等待先前的线程通过Release来释放。

bubuko.com,布布扣
    class Program
    {
        static void Main(string[] args)
        {

            Thread t1 = new Thread(Run1);
            t1.Start();

            Thread t2 = new Thread(Run2);
            t2.Start();

            Thread t3 = new Thread(Run3);
            t3.Start();

            Console.Read();
        }

        //初始可以授予2个线程信号,因为第3个要等待前面的Release才能得到信号
        static Semaphore sem = new Semaphore(2, 10);

        static void Run1()
        {
            sem.WaitOne();
            Console.WriteLine("大家好,我是Run1" + DateTime.Now.TimeOfDay);
        }

        static void Run2()
        {
            sem.WaitOne();
            Console.WriteLine("大家好,我是Run2" + DateTime.Now.TimeOfDay);

            //两秒后
            Thread.Sleep(2000);
            sem.Release();
        }

        static void Run3()
        {
            sem.WaitOne();
            Console.WriteLine("大家好,我是Run3" + DateTime.Now.TimeOfDay);
        }
    }
bubuko.com,布布扣

  输出:

  bubuko.com,布布扣

  在以上的方法中Release()方法相当于自增一个信号量,Release(5)自增5个信号量。但是,Release()到构造函数的第二个参数maximumCount的值就不能再自增了。

  命名Semaphore可用于进程级交互。

bubuko.com,布布扣
    class Program
    {
        static void Main(string[] args)
        {

            Thread t1 = new Thread(Run1);
            t1.Start();

            Thread t2 = new Thread(Run2);
            t2.Start();

            Console.Read();
        }
        
        //初始可以授予2个线程信号,因为第3个要等待前面的Release才能得到信号
        static Semaphore sem = new Semaphore(3, 10, "命名Semaphore");

        static void Run1()
        {
            sem.WaitOne();

            Console.WriteLine("进程:" +Process.GetCurrentProcess().Id + "  我是Run1" + DateTime.Now.TimeOfDay);
        }

        static void Run2()
        {
            sem.WaitOne();

            Console.WriteLine("进程:" + Process.GetCurrentProcess().Id + "  我是Run2" + DateTime.Now.TimeOfDay);
        }
    }
bubuko.com,布布扣

  输出如下:

  bubuko.com,布布扣

  •   ManualResetEvent:每次可以唤醒一个或多个线程;
  •   AutoResetEvent:每次只能唤醒一个线程;

信号量 <第六篇>

标签:blog   http   strong   ar   art   div   代码   log   sp   

原文地址:http://www.cnblogs.com/mingxuantongxue/p/3944420.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!