目录
1、CreateSemaphore
创建一个计数信号量对象,成功时返回信号量对象的句柄;失败时返回NULL;
HANDLE CreateSemaphore(
LPSECURITY_ATTRIBUTES lpSemaphoreAttributes, // 安全属性
LONG lInitialCount, // 初始计数
LONG lMaximumCount, // 最大计数
LPCTSTR lpName // 信号量的名字
);
- lpSemaphoreAttributes:指向 SECURITY_ATTRIBUTES 结构的指针,确定信号量的安全性。可以设置为 NULL。
- lInitialCount:信号量的初始计数值。
- lMaximumCount:信号量的最大计数值。
- lpName:信号量的名字。可以设置为 NULL,表示没有名字。
2、ReleaseSemaphore
增加信号量的计数值。成功时返回非零值;失败时返回 0。
BOOL ReleaseSemaphore(
HANDLE hSemaphore, // 信号量的句柄
LONG lReleaseCount, // 释放的计数值
LPLONG lpPreviousCount // 指向存储原始计数的变量的指针
);
- hSemaphore:信号量的句柄。
- lReleaseCount:增加的计数值。
- lpPreviousCount:指向存储增加前的计数值的变量的指针。可以设置为 NULL。
3、CreateEvent
创建一个事件对象,用于通知线程或进程发生了特定事件。成功时返回事件对象的句柄;失败时返回NULL。
HANDLE CreateEvent(
LPSECURITY_ATTRIBUTES lpEventAttributes, // 安全属性
BOOL bManualReset, // 是否手动重置事件
BOOL bInitialState, // 初始状态
LPCTSTR lpName // 事件的名字
);
- lpEventAttributes:指向 SECURITY_ATTRIBUTES 结构的指针,确定事件的安全性。可以设置为 NULL。
- bManualReset:指定事件是否需要手动重置。如果为 TRUE,则必须手动重置事件;如果为 FALSE,则系统会自动重置事件。
- bInitialState:事件的初始状态。如果为 TRUE,事件在创建时为有信号状态;如果为 FALSE,为无信号状态。
- lpName:事件的名字。可以设置为 NULL,表示没有名字。
4、SetEvent
设置事件对象为有信号状态。成功时返回非零值;失败时返回 0。
BOOL SetEvent(HANDLE hEvent);
- hEvent:事件对象的句柄。
5、WaitForSingleObject
等待一个对象的状态变为有信号状态,或者等待超时。
DWORD WaitForSingleObject(
HANDLE hHandle, // 对象的句柄
DWORD dwMilliseconds // 超时时间,单位为毫秒
);
参数:
- hHandle:对象的句柄,例如信号量或事件。
- dwMilliseconds:等待的超时时间。如果设置为 INFINITE,则表示无限等待直到对象变为有信号状态。
返回值:
- WAIT_OBJECT_0:对象变为有信号状态。
- WAIT_TIMEOUT:超时。
- WAIT_FAILED:函数失败。
程序案例1:
以下程序实现功能:
四个保存图像的线程; 一个信息发送的线程
当四个保存图像的线程都执行完毕之后,发送一次信号
#include <iostream>
#include <thread>
#include <Windows.h>
#include <vector>
using namespace std;
HANDLE steel_signal_end; // 用于通知主线程所有图像保存完成的事件
HANDLE semaphore; // 用于计数已完成图像保存的线程数
void save_image(int idex) {
while (true) {
Sleep(6000);
// 如果是最后一个完成保存的线程,设置事件
LONG previous_count;
// ReleaseSemaphore:信号量的句柄、增加的计数值、指向存储增加前的计数值的变量的指针
// 增加的计数值:函数中设为了1
if (ReleaseSemaphore(semaphore, 1, &previous_count) && previous_count + 1 == 4) {
cout << idex << "最后完成" << endl;
SetEvent(steel_signal_end);
}
}
}
void send_message() {
const int total_threads = 4;
// 创建手动重置事件,初始状态为非触发状态
steel_signal_end = CreateEvent(NULL, TRUE, FALSE, NULL); // 安全属性、是否手动重置事件、初始状态、事件的名字
// 创建计数信号量,初始计数为0,最大计数为total_threads
semaphore = CreateSemaphore(NULL, 0, total_threads, NULL); // 安全属性、初始计数、最大计数、信号量的名字
while (true) {
cout << "等待信号触发" << endl;
// 主线程等待所有图像保存完成
WaitForSingleObject(steel_signal_end, INFINITE);
CloseHandle(semaphore);
semaphore = CreateSemaphore(NULL, 0, total_threads, NULL);
cout << "一个批次完成" << endl;
// 重置事件以准备下一批图像的保存
ResetEvent(steel_signal_end);
}
}
int main() {
vector<std::thread> threads;
for (unsigned int i = 0; i <= 3; i++) {
threads.emplace_back(save_image, i);
}
threads.emplace_back(send_message);
for (auto& t : threads) {
t.join();
}
return 0;
}
程序案例2:
只使用计数信号量进行控制
#include <iostream>
#include <thread>
#include <Windows.h>
#include <vector>
using namespace std;
HANDLE semaphore;
void save_image() {
while (true) {
Sleep(5000);
ReleaseSemaphore(semaphore, 1, NULL);
}
}
void send_message() {
semaphore = CreateSemaphore(NULL, 0, 1, NULL); // 安全属性、初始计数、最大计数、信号量的名字
while (true) {
cout << "等待信号触发" << endl;
WaitForSingleObject(semaphore, INFINITE);
cout << "保存一次图片" << endl;
}
}
int main() {
vector<std::thread> threads;
threads.emplace_back(send_message);
threads.emplace_back(save_image);
for (auto& t : threads) {
t.join();
}
return 0;
}