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阻塞线程,使得线程有序的执行下去。

  • 相关阅读:
    八皇后问题--------------------递归回溯
    排序算法06------------------------插入排序
    无重复字符最长子串----------------滑动窗口法
    排序算法05------------------------堆排序(图解)
    排序算法04------------------------归并排序
    图形学基础(一)光栅图形学_下:剪裁
    计网Top-Down 抄书笔记(二)——应用层
    图形学基础(二)图形变换_下:3D 平行投影
    图形学基础(二)图形变换_上:2D 基本变换/复合变换
    图形学基础(一)光栅图形学_上:画直线/圆、区域填充
  • 原文地址:https://www.cnblogs.com/oneheart/p/5636359.html
Copyright © 2011-2022 走看看