zoukankan      html  css  js  c++  java
  • 浅析C#线程同步事件-WaitHandle

    官方:对共享资源的独占访问的操作系统特定的对象

    WaitHandle分为:Mutex,Semaphore,EventWaitHandle(分为AutoResetEvent,ManualResetEvent)

    一:AutoResetEvent-自动同步事件 

    class Program
        {
            static AutoResetEvent autoResetEvent = new AutoResetEvent(false);
            //static ManualResetEvent manualResetEvent = new ManualResetEvent(false);
            static int i = 1;//确保第一个数是奇数
            static void Main(string[] args)
            {          
                //任务:两个线层,分别打奇偶数
                Thread thread1 = new Thread(Test);
                thread1.Name = "奇数线层";
                thread1.Start();
                Thread.Sleep(1);//确保是奇数先运行
                Thread thread2 = new Thread(Test);
                thread2.Name = "偶数线层";
                thread2.Start();
                autoResetEvent.Set();//允许等待的线层继续执行
                Console.Read();  
            }
    
            static void Test()
            {
                while (i<10)
                {
                    if (i%2!=0)//积数
                    {
                        autoResetEvent.WaitOne();
                        Console.WriteLine(Thread.CurrentThread.Name+i++);
                        autoResetEvent.Set();
                    }
                    else//偶数
                    {
                        autoResetEvent.WaitOne();
                        Console.WriteLine(Thread.CurrentThread.Name + i++);
                        autoResetEvent.Set();
                    }             
                }
            }    
        }

    效果;,如果定义int i为0,由于起始是偶数的关系就需要先让偶数线层运行,原理相同。

    其中

    autoResetEvent.Set()只允许单一的一个状态改变,独占访问,即多线程时也只触发一次waitone()信号,由于此特性,所以代码每次waitone()后再次Set()就会实现多线层有序触发。
                如果没有
    waitone()后再次Set(),那代码只会执行一次waitone()。即Set后状态默认就为False。
    二:ManualResetEvent-手动同步事件

    class Program
        {
            //static AutoResetEvent autoResetEvent = new AutoResetEvent(false);
            static ManualResetEvent manualResetEvent = new ManualResetEvent(false);
            static int i = 1;//确保第一个数是奇数
            static void Main(string[] args)
            {          
                //任务:两个线层,分别打奇偶数
                Thread thread1 = new Thread(Test);
                thread1.Name = "奇数线层";
                thread1.Start();
                Thread.Sleep(1);//确保是奇数先运行
                Thread thread2 = new Thread(Test);
                thread2.Name = "偶数线层";
                thread2.Start();
                manualResetEvent.Set();//允许等待的线层继续执行
                Console.Read();  
            }
    
            static void Test()
            {
                while (i<10)
                {
                    if (i%2!=0)//积数
                    {
                        manualResetEvent.WaitOne();
                        Console.WriteLine(Thread.CurrentThread.Name+i++);
                        //manualResetEvent.Reset();
                    }
                    else//偶数
                    {
                        manualResetEvent.WaitOne();
                        Console.WriteLine(Thread.CurrentThread.Name + i++);
                        //manualResetEvent.Reset();
                    }             
                }
            }    
        }

    效果:允许多状态改变,同步多线程,即多线程时触发多次waitone()信号,永不停止持续触发,由于此特性,所以代码就会实现多线层无序触发。

             想要代码只会执行一次waitone(),就需要调用Reset()。即Manual的Set后状态默认就为true,只有Reset后会将状态默认改为False。

    总结:主要是为了线程同步事件,区别就是Auto只开一次就默认主动关一次,需要使用得再次打开;Manual开一次后就默认一直开,需要关时候才调用关。
       构造函数时定义true就不需要第一次Set。其中WaitOne函数防止死锁时重载WaitOne(100,false),超时时也会将状态置为False。



    三:
    Semaphore-信号量
    private static readonly int MaxSize = 1;
            private static int i = 0;
            static Semaphore semaphore = new Semaphore(0, MaxSize);
    
            static void Main(string[] args)
            {
                Thread thread1 = new Thread(new ThreadStart(show));
                thread1.Name = "偶数线程";
                Thread thread2 = new Thread(new ThreadStart(show));
                thread2.Name = "奇数线程";
                thread1.Start();
                Thread.Sleep(1);
                thread2.Start();
                Console.Read();
            }
    
            private static void show()
            {
                if (i == 1) semaphore.WaitOne();
                while (i <= 10)
                {
                    int num = i % 2;
                    if (num == 0)
                    {
                        Console.WriteLine("{0}:{1}  {2}    ", Thread.CurrentThread.Name, i++, Thread.CurrentThread.ManagedThreadId);
                        semaphore.Release();
                        semaphore.WaitOne(); //当前线程阻塞
                    }
                    else
                    {
                        Console.WriteLine("{0}:{1}  {2}    ", Thread.CurrentThread.Name, i++, Thread.CurrentThread.ManagedThreadId);
                        semaphore.Release();
                        semaphore.WaitOne(); //当前线程阻塞
                    }
                }
            }

    结果:




    其余线程同步问题参考:https://www.cnblogs.com/zhan520g/p/11388591.html
                 https://www.cnblogs.com/michaelxu/archive/2008/09/20/1293716.html
  • 相关阅读:
    [TC_SRM_466]DrawingBlackCrosses
    [POJ3254]Corn Fields
    [openjudge6043]哆啦A梦的时光机
    网络流 24 题汇总(LOJ 上只有 22 题???)
    Xadmin组件的url设计
    《今日简史》一、旧故事已然崩坏,新故事尚未构建
    《人类简史》二、认知革命——上帝之手的秘密
    ORM复习
    无拘无束的爱情
    使用代理导致IE host被修改问题的解决方案
  • 原文地址:https://www.cnblogs.com/shenhuawen/p/14268045.html
Copyright © 2011-2022 走看看