一、線程同步
1、線程同步
多線程程序設計大多會涉及線程間相互通信。主線程在創建工作線程以後,工作線程之間還需要通過通信機制來協同工作。一種比較好的方法就是使用事件內核對象。
事件內核對象是一種用於多線程同步和他們之間的通信手段。
同步可以保證在一個時間內只有一個線程對某個共享資源有控制權。
2、汽車東西走向與南北走向協調的問題
二、事件內核對象
1、事件內核對象
事件內核對象是一種抽象的對象,它也有未受信和受信兩種狀態,可以使用WaitForSingleObject函數等待其變成受信狀態。不同於其他內核對象的一些函數可以使實踐對象在這兩種狀態之間轉換。可以把時間對象看成是一個設置在Windows內部的一個標誌。它的狀態設置和測試工作由Windows來完成。
時間對象包含3個成員:
nUsageCount:使用計數
bManualReset:是否人工重置
bSignaled:是否受信
2、基本函數
//使用CreateEvent函數創建事件對象:
HANDLE CreateEvent(LPSECURITY_ATTRIBUTES lpEventAttributes, // 用來定義事件對象的安全屬性
BOOL bManualReset, // 指定是否需要手工重置事件對象爲受信狀態
BOOL bInitialState, // 指定事件對象創建時的初始狀態
LPCWSTR lpName); // 事件對象的名稱
//根據lpName對象的名字查詢,返回事件對象句柄:
HANDLE OpenEvent(DWORD dwDesiredAccess, // 指定想要的訪問權限
BOOL bInheritHandle, // 指定返回句柄是否被繼承
LPCWSTR lpName); // 要打開的事件對象的名稱
BOOL SetEvent(HANDLE hEvent); // 將事件狀態設置爲受信狀態
BOOL ReSetEvent(HANDLE hEvent); // 將事件狀態設置爲未受信狀態
三、實例
1、多線程同步,實現兩個線程交互打印A、B
#include <stdio.h>
#include <windows.h>
#include <process.h>
HANDLE g_hEventEW,g_hEventNS; // 東西與南北事件
UINT _stdcall ProcessA(LPVOID lpParam)
{
while (true)
{
WaitForSingleObject(g_hEventEW, INFINITE);
printf("A\n");
SetEvent(g_hEventNS);
Sleep(200);
}
return 0;
}
UINT _stdcall ProcessB(LPVOID lpParam)
{
while (true)
{
WaitForSingleObject(g_hEventNS, INFINITE);
printf("B\n");
SetEvent(g_hEventEW);
Sleep(200);
}
return 0;
}
int main()
{
HANDLE H[2];
H[0] = (HANDLE)_beginthreadex(NULL, 0, ProcessA, NULL, 0, NULL);
H[1] = (HANDLE)_beginthreadex(NULL, 0, ProcessB, NULL, 0, NULL);
// 問題1:主線程如何調用A,B兩個線程
// 東西向的先走
g_hEventEW = CreateEvent(NULL, FALSE, TRUE, NULL);
g_hEventNS = CreateEvent(NULL, FALSE, FALSE, NULL);
WaitForMultipleObjects(2, H, TRUE, INFINITE); // 無限等待
// 問題2:A、B如何交互打印
system("pause");
return 0;
}
2、實驗結果