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


     

    目录

    1、CreateSemaphore

    2、ReleaseSemaphore

    3、CreateEvent

    4、SetEvent

    5、WaitForSingleObject

    程序案例1:

    程序案例2:


    1、CreateSemaphore

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

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

    2、ReleaseSemaphore

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

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

    3、CreateEvent

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

    1. HANDLE CreateEvent(
    2. LPSECURITY_ATTRIBUTES lpEventAttributes, // 安全属性
    3. BOOL bManualReset, // 是否手动重置事件
    4. BOOL bInitialState, // 初始状态
    5. LPCTSTR lpName // 事件的名字
    6. );
    • lpEventAttributes:指向 SECURITY_ATTRIBUTES 结构的指针,确定事件的安全性。可以设置为 NULL。
    • bManualReset:指定事件是否需要手动重置。如果为 TRUE,则必须手动重置事件;如果为 FALSE,则系统会自动重置事件。
    • bInitialState:事件的初始状态。如果为 TRUE,事件在创建时为有信号状态;如果为 FALSE,为无信号状态。
    • lpName:事件的名字。可以设置为 NULL,表示没有名字。

    4、SetEvent

    设置事件对象为有信号状态。成功时返回非零值;失败时返回 0。

    BOOL SetEvent(HANDLE hEvent);
    
    • hEvent:事件对象的句柄。

    5、WaitForSingleObject

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

    1. DWORD WaitForSingleObject(
    2. HANDLE hHandle, // 对象的句柄
    3. DWORD dwMilliseconds // 超时时间,单位为毫秒
    4. );

     参数:

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

    返回值:

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

    程序案例1:

    以下程序实现功能:

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

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

    1. #include
    2. #include
    3. #include
    4. #include
    5. using namespace std;
    6. HANDLE steel_signal_end; // 用于通知主线程所有图像保存完成的事件
    7. HANDLE semaphore; // 用于计数已完成图像保存的线程数
    8. void save_image(int idex) {
    9. while (true) {
    10. Sleep(6000);
    11. // 如果是最后一个完成保存的线程,设置事件
    12. LONG previous_count;
    13. // ReleaseSemaphore:信号量的句柄、增加的计数值、指向存储增加前的计数值的变量的指针
    14. // 增加的计数值:函数中设为了1
    15. if (ReleaseSemaphore(semaphore, 1, &previous_count) && previous_count + 1 == 4) {
    16. cout << idex << "最后完成" << endl;
    17. SetEvent(steel_signal_end);
    18. }
    19. }
    20. }
    21. void send_message() {
    22. const int total_threads = 4;
    23. // 创建手动重置事件,初始状态为非触发状态
    24. steel_signal_end = CreateEvent(NULL, TRUE, FALSE, NULL); // 安全属性、是否手动重置事件、初始状态、事件的名字
    25. // 创建计数信号量,初始计数为0,最大计数为total_threads
    26. semaphore = CreateSemaphore(NULL, 0, total_threads, NULL); // 安全属性、初始计数、最大计数、信号量的名字
    27. while (true) {
    28. cout << "等待信号触发" << endl;
    29. // 主线程等待所有图像保存完成
    30. WaitForSingleObject(steel_signal_end, INFINITE);
    31. CloseHandle(semaphore);
    32. semaphore = CreateSemaphore(NULL, 0, total_threads, NULL);
    33. cout << "一个批次完成" << endl;
    34. // 重置事件以准备下一批图像的保存
    35. ResetEvent(steel_signal_end);
    36. }
    37. }
    38. int main() {
    39. vector threads;
    40. for (unsigned int i = 0; i <= 3; i++) {
    41. threads.emplace_back(save_image, i);
    42. }
    43. threads.emplace_back(send_message);
    44. for (auto& t : threads) {
    45. t.join();
    46. }
    47. return 0;
    48. }

    程序案例2:

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

    1. #include
    2. #include
    3. #include
    4. #include
    5. using namespace std;
    6. HANDLE semaphore;
    7. void save_image() {
    8. while (true) {
    9. Sleep(5000);
    10. ReleaseSemaphore(semaphore, 1, NULL);
    11. }
    12. }
    13. void send_message() {
    14. semaphore = CreateSemaphore(NULL, 0, 1, NULL); // 安全属性、初始计数、最大计数、信号量的名字
    15. while (true) {
    16. cout << "等待信号触发" << endl;
    17. WaitForSingleObject(semaphore, INFINITE);
    18. cout << "保存一次图片" << endl;
    19. }
    20. }
    21. int main() {
    22. vector threads;
    23. threads.emplace_back(send_message);
    24. threads.emplace_back(save_image);
    25. for (auto& t : threads) {
    26. t.join();
    27. }
    28. return 0;
    29. }

  • 相关阅读:
    LS1043A LSDK2108写入EMMC 未完待续
    达梦数据库的名词解释
    ASEMI快恢复二极管SFP4006,SFP4006参数,SFP4006应用
    创建数字藏品艺术平台需要多少成本
    npm install 太慢?解决方法
    docker学习记录(二)
    41. ES6 中模板语法与字符串处理?
    Oracle VM VirtualBox虚拟机安装的 Linux系统中的虚拟机和Windows 10客户机时间不同步设置
    Java 并发编程学习总结
    C#根据DataTable中的不同值为asp:DataGrid中的不同行或单元格设置不同的颜色
  • 原文地址:https://blog.csdn.net/Word_And_Me_/article/details/141072442