线程同步之事件

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

时间: 2024-08-25 09:59:34

线程同步之事件的相关文章

VC++深入详解——16章:线程同步,事件对象

这章介绍另外:事件对象和关键代码段. 进程相关函数: CreateEvent函数: 第一个参数:安全属性,默认的安全属性为NULL 第二个参数:复位方式, 人工设置为TRUE,自动设置为FALSE, 当为人工设置时,等待事件的线程时,需要resetevent函数来设置其为无型号状态. 第三个参数:初始状态:TRUE为有信号状态,FALSE为无信号状态. 第四个参数:对象名称,NULL为匿名名称. 创建或打开一个命名或匿名的事件对象(也属于内核对象) 返回:返回的是事件对象的句柄. SetEven

VC++线程同步(四) 事件使用例子

事件(Event)同步对象 (内核级别)事件内核对象包含: 1 一个使用计数器 2 一个表示事件是否是自动重置还是手动重置的布尔值 3 一个表示事件有没有被触发的布尔值 4 当触发为true时,等待该事件的线程变为可调度状态 5 事件的触发表示一个操作已经完成 作用: 通知其他线程,我已经完成读写操作了,轮到你们来做了. 他分为两种类型: 1是手动重置事件,也就是要进行手动的触发和非触发状态的切换. 2是自动重置事件,这种情况下只需要设置触发事件,不用管什么时候切换触发状态. 尽量使用手动重置方

C++线程同步之事件

题目要求:点击抢红包后,先将第一个编辑框的值设置为1000,然后创建三个线程,让右边的编辑框值依次设置为1000(用事件完成) // MutexExDlg.h : 头文件 // #pragma once // CMutexExDlg 对话框 class CMutexExDlg : public CDialogEx { // 构造 public: CMutexExDlg(CWnd* pParent = NULL); // 标准构造函数 // 对话框数据 enum { IDD = IDD_MUTEX

MFC线程(三):线程同步事件(event)与互斥(mutex)

前面讲了临界区可以用来达到线程同步.而事件(event)与互斥(mutex)也同样可以做到. Win32 API中的线程事件 HANDLE hEvent = NULL; void MainTestFun{ hEvent = CreateEvent(NULL,FALSE,FALSE,NULL); SetEvent(hEvent); char g_charArray[4]; CString szResult; //下面三个线程中的任意一个访问g_charArray的时候其他线程都不能访问 AfxBe

C++技术问题总结-第3篇 线程同步

线程同步的方法 线程同步有多种方法. 用户模式下的线程同步:关键段(critcal section). 内核模式下的线程同步:事件.计时器.信号量.互斥量. 1.关键段 用户模式下的同步,主要API如下. InitializeCriticalSection.DeleteCriticalSection.EnterCriticalSection.LeaveCriticalSection. 2.事件 常用于:一个线程初始化工作,然后再触发另一个线程让它工作.主要API如下. CreateEvent.S

C#多线程:深入了解线程同步lock,Monitor,Mutex,同步事件和等待句柄(中)

本篇继续介绍WaitHandler类及其子类 Mutex,ManualResetEvent,AutoResetEvent的用法..NET中线程同步的方式多的让人看了眼花缭乱,究竟该怎么去理解呢?其实,我们抛开.NET环境看线程同步,无非是执行两种操作:一是互斥/加锁,目的是保证临界区代码操作的"原子性":另一种是信号灯操作,目的是保证多个线程按照一定顺序执行,如生产者线程要先于消费者线程执行..NET中线程同步的类无非是对这两种方式的封装,目的归根结底都可以归结为实现互斥/ 加锁或者是

秒杀多线程第九篇 经典线程同步总结 关键段 事件 互斥量 信号量

版权声明:本文为博主原创文章,未经博主允许不得转载. 前面<秒杀多线程第四篇一个经典的多线程同步问题>提出了一个经典的多线程同步互斥问题,这个问题包括了主线程与子线程的同步,子线程间的互斥,是一道非常经典的多线程同步互斥问题范例,后面分别用了四篇 <秒杀多线程第五篇经典线程同步关键段CS> <秒杀多线程第六篇经典线程同步事件Event> <秒杀多线程第七篇经典线程同步互斥量Mutex> <秒杀多线程第八篇经典线程同步信号量Semaphore> 来

进程、线程同步互斥学习 —— 事件

关于事件,先看MSDN介绍: Event Objects Anevent object is a synchronization object whose state can be explicitly set to signaled by use of theSetEvent function. 即:Event与其他线程同步不同,Event可以通过函数来设置有无信号量. 初始化 A thread uses theCreateEvent or CreateEventEx function to

多线程实现线程同步——事件对象

事件对象是指在程序中使用内核对象的有无信号状态实现线程的同步. 1.使用API函数操作事件对象 API函数为CreateEvent: 函数原型为: HANDLE CreateEvent( LPSECURITY_ATTRIBUTES lpEventAttributes, // SD BOOL bManualReset, // reset type BOOL bInitialState, // initial state LPCTSTR lpName // object name); 参数lpEve