1. 程式人生 > >多執行緒系列之——事件核心物件

多執行緒系列之——事件核心物件

所有核心物件裡面事件核心物件是最簡單的一個,它包括一個使用計數,還有兩個布林值。一個布林值用來表示事件是手動重置事件還是自動重置事件,另一個布林值表示當前是否處於觸發狀態。

當一個手動重置事件被觸發的時候,所有等待該事件的執行緒都能變成排程狀態。而一個自動重置事件被觸發的時候,等待該事件的執行緒裡面只有一個會變成排程狀態。

建立一個事件的函式原型如下:

HANDLE WINAPI CreateEvent(
  __in_opt  LPSECURITY_ATTRIBUTES lpEventAttributes,
  __in      BOOL bManualReset,
  __in      BOOL bInitialState,
  __in_opt  LPCTSTR lpName
);

第一個引數是安全描述符,設為NULL表示使用預設的安全描述符,並且子程序無法繼承返回的控制代碼。

第二個引數TRUE表示手動重置,FALSE表示自動重置。

第三個引數FALSE表示事件是未觸發狀態,TRUE表示事件是觸發狀態。

第四個引數為事件指定一個名字。如果已經存在,如果已經存在,函式則請求事件的EVENT_ALL_ACCESS許可權,此時其它引數將被忽略。(程式只執行一個例項就可以使用這個方法,檢測到事件已經存在則退出)

SetEvent設定事件為觸發狀態,ResetEvent設定事件為未觸發狀態。

控制代碼一定要關閉,通過CloseHandle。

WaitForSingleOeject和WaitForMultipleObjects對自動重置事件有個副作用,等待成功後會將事件重置為未觸發狀態。

通過兩個例子程式來感受下事件的便利。

現在有三個顧客進了菸酒店,分別要了三包不通的香菸,老闆去取香菸,這三個顧客就在櫃檯前等待(等待事件),老闆取來了香菸(事件變成觸發狀態),付賬、拿煙、離開。

第一個例子程式使用手動重置事件,事件出發後,三個顧客可以同時離開。

#include <windows.h>
#include <iostream>

using namespace std;

HANDLE hEvent;//全域性事件

DWORD WINAPI CustomerOne(LPVOID lp)
{
	cout << "顧客1:老闆,拿包8mg的紅雙喜" << endl;
	WaitForSingleObject(hEvent,INFINITE);
	cout << "顧客1:這種紅雙喜非常清爽,謝謝。" << endl;

	return 0;
}

DWORD WINAPI CustomerTwo(LPVOID lp)
{
	cout << "顧客2:14塊的利群" << endl;
	WaitForSingleObject(hEvent,INFINITE);
	cout << "顧客2:我喜歡這個香菸,謝謝老闆。" << endl;

	return 0;
}

DWORD WINAPI CustomerThree(LPVOID lp)
{
	cout << "顧客3:我要包8mg的中南海" << endl;
	WaitForSingleObject(hEvent,INFINITE);
	cout << "顧客3:一般人抽不慣這個,不過我一直都抽這個。" << endl;

	return 0;
}

int main(int argc, char *argv[])
{
	hEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
	HANDLE hThread[3];
	hThread[0] = CreateThread(NULL,0,CustomerOne,0,0,NULL);
	hThread[1] = CreateThread(NULL,0,CustomerTwo,0,0,NULL);
	hThread[2] = CreateThread(NULL,0,CustomerThree,0,0,NULL);

	Sleep(1000);
	cout << "老闆:你們要的香菸。" << endl;
	SetEvent(hEvent);

	WaitForMultipleObjects(3,hThread,TRUE,INFINITE);
	cout << endl << "所有執行緒都退出" << endl;

	CloseHandle(hEvent);
	for(int i = 0;i < 3;++i)
		CloseHandle(hThread[i]);

	return 0;
}


第二個例子使用自動重置事件,三個顧客分別先後離開。(等待成功的副作用,所以三個執行緒不能同時執行。每個執行緒等待成功後必須重置事件為觸發狀態,這樣另外的執行緒就有機會得到執行。)
#include <windows.h>
#include <iostream>

using namespace std;

HANDLE hEvent;//全域性事件

DWORD WINAPI CustomerOne(LPVOID lp)
{
	cout << "顧客1:老闆,拿包8mg的紅雙喜" << endl;
	WaitForSingleObject(hEvent,INFINITE);
	cout << "顧客1:這種紅雙喜非常清爽,謝謝。" << endl;
	SetEvent(hEvent);
	cout << "顧客1離開。" << endl;

	return 0;
}

DWORD WINAPI CustomerTwo(LPVOID lp)
{
	cout << "顧客2:14塊的利群" << endl;
	WaitForSingleObject(hEvent,INFINITE);
	cout << "顧客2:我喜歡這個香菸,謝謝老闆。" << endl;
	SetEvent(hEvent);
	cout << "顧客2離開。" << endl;

	return 0;
}

DWORD WINAPI CustomerThree(LPVOID lp)
{
	cout << "顧客3:我要包8mg的中南海" << endl;
	WaitForSingleObject(hEvent,INFINITE);
	cout << "顧客3:一般人抽不慣這個,不過我一直都抽這個。" << endl;
	SetEvent(hEvent);
	cout << "顧客3離開。" << endl;

	return 0;
}

int main(int argc, char *argv[])
{
	hEvent = CreateEvent(NULL,FALSE,FALSE,NULL);
	HANDLE hThread[3];
	hThread[0] = CreateThread(NULL,0,CustomerOne,0,0,NULL);
	hThread[1] = CreateThread(NULL,0,CustomerTwo,0,0,NULL);
	hThread[2] = CreateThread(NULL,0,CustomerThree,0,0,NULL);

	Sleep(1000);
	cout << "老闆:你們要的香菸。" << endl;
	SetEvent(hEvent);

	WaitForMultipleObjects(3,hThread,TRUE,INFINITE);
	cout << endl << "所有執行緒都退出" << endl;

	CloseHandle(hEvent);
	for(int i = 0;i < 3;++i)
		CloseHandle(hThread[i]);

	return 0;
}


非常感謝海盜,受益匪淺!

相關推薦

執行系列——事件核心物件

所有核心物件裡面事件核心物件是最簡單的一個,它包括一個使用計數,還有兩個布林值。一個布林值用來表示事件是手動重置事件還是自動重置事件,另一個布林值表示當前是否處於觸發狀態。 當一個手動重置事件被觸發的時候,所有等待該事件的執行緒都能變成排程狀態。而一個自動重置事件被觸發

java執行系列模式|第一篇-Guarded Suspension pattern

Guarded Suspension pattern模式 作者注:該系列文章基於《java執行緒設計模式》撰寫,只用於學習和交流。 定義:多執行緒執行,當前執行緒沒有達到警戒條件時,執行緒會進入等待直到

java執行系列模式|第三篇: Producer-Consumer pattern

生產者-消費者模式 含義:顧名思義,生產者用來生產資料,可能有一到多個,消費者用來消費資料,也可能有多個,中間會有一個“橋樑參與者”,作為資料的存放以及執行緒之間的同步和協調。 範例程式行為: 廚師(MakerThread)做蛋糕,做好後放在桌子(Table)上 桌子

執行系列 java執行的個人理解(二)

  前言:上一篇多執行緒系列之 java多執行緒的個人理解(一) 講到了執行緒、程序、多執行緒的基本概念,以及多執行緒在java中的基本實現方式,本篇主要接著上一篇繼續講述多執行緒在實際專案中的應用以及遇到的諸多問題和解決方案

執行同步事件 -- 2個執行交替列印數字

    有段時間沒有接觸多執行緒相關的知識了,難免會遺忘或者生疏。多執行緒通訊和同步相關的知識運用比較廣,而且比較常見。今天通過2個執行緒交替列印數字的例子,來整理下多執行緒序相關的程式設計方式。這裡2個執行緒直接通過一個event進行同步。     我們通過CreateE

Android進階——執行系列非同步任務AsyncTask的使用與原始碼分析

AsyncTask是什麼 AsyncTask是一種輕量級的非同步任務類,它可以線上程池中執行後臺任務,然後把執行的進度和最終結果傳遞給主執行緒並主執行緒中更新UI,通過AsyncTask可以更加方便執行後臺任務以及在主執行緒中訪問UI,但是AsyncTask並

C++執行同步事件(Event)

一、事件(Event)原理解析 1、執行緒同步Event,主要用於執行緒間的等待通知。 2、核心物件中,事件核心物件是個最基本的物件。 3、事件包含一個使用計數(與所有核心物件一樣),一個用於指明該事件是個自動重置的事件還是人工重置的事件的布林值,另一個用

Android進階——執行系列wait、notify、sleep、join、yield、synchronized關鍵字、ReentrantLock鎖

前言 多執行緒一直是初學者最困惑的地方,每次看到一篇文章,覺得很有難度,就馬上叉掉,不看了,我以前也是這樣過來的。後來,我發現這樣的態度不行,知難而退,永遠進步不了。於是,我狠下心來看完別人的部落格,儘管很難但還是咬著牙,不懂去查閱資料,到最後弄懂整個過程。雖

Java執行系列--“JUC原子類”03 AtomicLong原子類

轉自:https://www.cnblogs.com/skywang12345/p/3514593.html(含部分修改) 概要 AtomicInteger, AtomicLong和AtomicBoolean這3個基本型別的原子類的原理和用法相似。本章以AtomicLong對基本型別的原子類進行介紹。內容

Java執行系列---“JUC原子類”04 AtomicLongArray原子類

轉自:https://www.cnblogs.com/skywang12345/p/3514604.html(含部分修改) 概要 AtomicIntegerArray, AtomicLongArray, AtomicReferenceArray這3個數組型別的原子類的原理和用法相似。本章以AtomicLo

Java執行系列---“JUC原子類”05 AtomicReference原子類

轉自:http://www.cnblogs.com/skywang12345/p/3514623.html(部分修改) 概要 本章對AtomicReference引用型別的原子類進行介紹。內容包括: AtomicReference介紹和函式列表 AtomicReference原始碼分析(基於J

Java執行系列---“JUC原子類”06 AtomicLongFieldUpdater原子類

轉自:http://www.cnblogs.com/skywang12345/p/3514635.html (含部分修改) 概要 AtomicIntegerFieldUpdater, AtomicLongFieldUpdater和AtomicReferenceFieldUpdater這3個修改類的成員的原

Java執行系列---“JUC原子類”01 原子類的實現(CAS演算法)

轉自:https://blog.csdn.net/ls5718/article/details/52563959  & https://blog.csdn.net/mmoren/article/details/79185862(含部分修改)   在JDK 5之前Java語言是靠

Java執行系列---“JUC原子類”02 框架

轉自:http://www.cnblogs.com/skywang12345/p/3514589.html   根據修改的資料型別,可以將JUC包中的原子操作類可以分為4類。 1. 基本型別: AtomicInteger, AtomicLong, AtomicBoolean ;2.&

Java執行系列---“JUC鎖”01 框架

轉自:http://www.cnblogs.com/skywang12345/p/3496098.html(含部分修改)   本章,我們介紹鎖的架構;後面的章節將會對它們逐個進行分析介紹。目錄如下: 01. Java多執行緒系列--“JUC鎖”01之 框架 02. 

Java執行系列---“JUC鎖”02 ReentrantLock

轉自:https://www.jianshu.com/p/96c89e6e7e90 & https://blog.csdn.net/Somhu/article/details/78874634 (含部分修改) 一.ReentrantLock鎖 1.Lock介面 Lock,鎖

java執行系列翻譯java併發/執行教程

原文地址:http://tutorials.jenkov.com/java-concurrency/index.html 以前計算機都是單核,同時只能執行一個程式。之後出現了多重任務處理,這意味著計算機同時可以處理多個程式(又名任務或流程)。但這不是真正的“同時執行”,只是單個CPU被多個程式共

Java執行系列---“基礎篇”14 wait,sleep,join,yield,park,unpark,notify等通訊機制對比

1. 執行緒讓步: yield() yield()的作用是讓步。它能讓當前執行緒由“執行狀態”進入到“就緒狀態”,從而讓其它具有相同優先順序的等待執行緒獲取執行權;但是,並不能保證在當前執行緒呼叫yield()之後,其它具有相同優先順序的執行緒就一定能獲得執行權;也有可能是當前執行緒又進入到“執行狀態”繼續

Java執行系列---“JUC鎖”06 公平鎖(下)

轉自:http://www.cnblogs.com/skywang12345/p/3496609.html 釋放公平鎖(基於JDK1.7.0_40) 1. unlock() unlock()在ReentrantLock.java中實現的,原始碼如下: public void unlock() {

Java執行系列--“JUC執行池”01 執行池架構

概要 前面分別介紹了”Java多執行緒基礎”、”JUC原子類”和”JUC鎖”。本章介紹JUC的最後一部分的內容——執行緒池。內容包括: 執行緒池架構圖 執行緒池示例 執行緒池架構圖 執行緒池的架構圖如下: 1、Executor