zoukankan      html  css  js  c++  java
  • 线程同步之事件

      我们可以使用lock、Mutex来保证共享资源被正确的操作,但当多个线程之间需要相互通信时,如线程A完成之后要告诉线程B,B在接着做,

    这时我们应该怎么处理,那就要用到线程的事件。.Net中提供了AutoResetEvent和ManualResetEvent两个类来处理。

      当线程需要独占资源时,使用AutoResetEvent.WaitOne()来等待资源,如果AutoResetEvent为非终止状态,则线程阻塞,等待其它线程释放资源。其它线程

    使用完资源,通过调用Set方法来释放资源,通知等待线程资源可用。第一个等待的线程接到信号之后即可占用资源继续执行,当线程执行完毕,会自动将AutoResetEvent设置

    为终止状态。

    AutoResetEvent 在初始化时通过参数来设置初始化状态,true表示终止状态,false表示非终止状态。

    我们来看一个例子。

    分两个人完成植树,A负责挖树坑,B负责搬树苗及浇水。代码实现如下:

    public class ThreadEventTest
        {
            private static AutoResetEvent autoResetEvent = new AutoResetEvent(false);
            public static void PlantTree()
            {
                //挖坑
                Thread shovelThread = new Thread(new ThreadStart(Shovel));
                shovelThread.Name = "A";
                shovelThread.Start();
                Thread.Sleep(100);
                //种树浇水
                Thread warterThread = new Thread(new ThreadStart(WarterTree));
                warterThread.Name = "B";
                warterThread.Start();            
            }
    
            private static void Shovel()
            {            
                Console.WriteLine("线程{0}开始挖坑",Thread.CurrentThread.Name);            
                Console.WriteLine("线程{0}挖坑完成,可以种树浇水了", Thread.CurrentThread.Name);
                autoResetEvent.Set();
            }
    
            private static void WarterTree()
            {            
                Console.WriteLine("线程{0}开始搬运树苗并准备水", Thread.CurrentThread.Name);                        
                Console.WriteLine("线程{0}已将树苗和水准备就绪,等待挖坑完成后可以种树浇水了", Thread.CurrentThread.Name);
                autoResetEvent.WaitOne();
    
                Console.WriteLine("线程{0}开始种树浇水", Thread.CurrentThread.Name);
                Thread.Sleep(1000);
                Console.WriteLine("线程{0}种树浇水完成", Thread.CurrentThread.Name);
                //
                Console.WriteLine("完成植树");
            }
        }

    主线程开启两个线程A、B分别完成挖坑和浇水。A线程不受限制开启后会执行挖坑任务,此时B线程也会同步执行,但当B线程执行值WaitOne时,由于我们初始化的AutoResetEvent状态为非终止状态,因此B线程必须等待Set信号,只有当A线程执行完毕并进行Set时,即A线程挖坑完成,B线程才能进行植树浇水,从而保证了整个

    植树工作有序的完成。

    AutoResetEvent在Set之后状态变为终止状态,当WaitOne执行之后又会自动将状态重置为非终止状态,而无需调用Reset(),这就是和ManualResetEvent之间的区别。

    ManualResetEvent在Set之后必须要Reset才能重置状态,调用需要成对出现,才能保证WaitOne阻塞线程,使得线程有序的执行下去。

  • 相关阅读:
    Linq to OBJECT延时标准查询操作符
    LINQ to XML
    动态Linq(结合反射)
    HDU 1242 dFS 找目标最短路
    HDu1241 DFS搜索
    hdu 1224 最长路
    BOJ 2773 第K个与m互质的数
    ZOJ 2562 反素数
    2016 ccpc 杭州赛区的总结
    bfs UESTC 381 Knight and Rook
  • 原文地址:https://www.cnblogs.com/oneheart/p/5636359.html
Copyright © 2011-2022 走看看