【学习笔记】多进程信号量控制

目录

1、CreateSemaphore

2、ReleaseSemaphore

3、CreateEvent

4、SetEvent

5、WaitForSingleObject

程序案例1:

程序案例2:


1、CreateSemaphore

创建一个计数信号量对象,成功时返回信号量对象的句柄;失败时返回NULL;

cpp 复制代码
HANDLE CreateSemaphore(
  LPSECURITY_ATTRIBUTES lpSemaphoreAttributes, // 安全属性
  LONG lInitialCount,                          // 初始计数
  LONG lMaximumCount,                          // 最大计数
  LPCTSTR lpName                               // 信号量的名字
);
  • lpSemaphoreAttributes:指向 SECURITY_ATTRIBUTES 结构的指针,确定信号量的安全性。可以设置为 NULL。
  • lInitialCount:信号量的初始计数值。
  • lMaximumCount:信号量的最大计数值。
  • lpName:信号量的名字。可以设置为 NULL,表示没有名字。

2、ReleaseSemaphore

增加信号量的计数值。成功时返回非零值;失败时返回 0。

cpp 复制代码
BOOL ReleaseSemaphore(
  HANDLE hSemaphore, // 信号量的句柄
  LONG lReleaseCount, // 释放的计数值
  LPLONG lpPreviousCount // 指向存储原始计数的变量的指针
);
  • hSemaphore:信号量的句柄。
  • lReleaseCount:增加的计数值。
  • lpPreviousCount:指向存储增加前的计数值的变量的指针。可以设置为 NULL。

3、CreateEvent

创建一个事件对象,用于通知线程或进程发生了特定事件。成功时返回事件对象的句柄;失败时返回NULL。

cpp 复制代码
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。

cpp 复制代码
BOOL SetEvent(HANDLE hEvent);
  • hEvent:事件对象的句柄。

5、WaitForSingleObject

等待一个对象的状态变为有信号状态,或者等待超时。

cpp 复制代码
DWORD WaitForSingleObject(
  HANDLE hHandle,   // 对象的句柄
  DWORD dwMilliseconds // 超时时间,单位为毫秒
);

参数:

  • hHandle:对象的句柄,例如信号量或事件。
  • dwMilliseconds:等待的超时时间。如果设置为 INFINITE,则表示无限等待直到对象变为有信号状态。

返回值:

  • WAIT_OBJECT_0:对象变为有信号状态。
  • WAIT_TIMEOUT:超时。
  • WAIT_FAILED:函数失败。

程序案例1:

以下程序实现功能:

四个保存图像的线程; 一个信息发送的线程

当四个保存图像的线程都执行完毕之后,发送一次信号

cpp 复制代码
#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:

只使用计数信号量进行控制

cpp 复制代码
#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;
}
相关推荐
咔咔学姐kk19 分钟前
大模型微调技术宝典:Transformer架构,从小白到专家
人工智能·深度学习·学习·算法·transformer
Jayyih1 小时前
嵌入式系统学习Day35(sqlite3数据库)
数据库·学习·sqlite
lingggggaaaa3 小时前
小迪安全v2023学习笔记(八十一讲)—— 框架安全&ThinkPHP&Laravel&Struts2&SpringBoot&CVE复现
笔记·学习·struts·安全·网络安全·laravel
CC数分3 小时前
零基础3个月上岸[特殊字符]自学数据分析路线
学习·数据挖掘·数据分析·大学生·考证
HAH-HAH3 小时前
【蓝桥杯 2024 国 Java A】粉刷匠小蓝
c++·学习·数学·算法·职场和发展·蓝桥杯·组合数学
酷讯网络_2408701603 小时前
多语言共享贩卖机投资理财共享售卖机投资理财系统
学习·开源
番薯大佬4 小时前
Python学习-day8 元组tuple
java·python·学习
wanzhong23334 小时前
ArcGIS学习-17 实战-密度分析
学习·arcgis
知识分享小能手4 小时前
React学习教程,从入门到精通,React 组件生命周期详解(适用于 React 16.3+,推荐函数组件 + Hooks)(17)
前端·javascript·vue.js·学习·react.js·前端框架·vue3
ooolmf5 小时前
照度传感器考虑笔记
笔记·单片机