【Windows线程开发】Windows线程同步技术(下)

简介: 【Windows线程开发】Windows线程同步技术(下)

三.事件

前两个技术都属于加锁技术,即两个线程互斥的时候使用,那么线程也会有协调工作的时候,这时候就需要用到我们的事件和信号量了。

  • 相关问题:
    多线程协调工作的时候的通知问题
  • 事件的使用
HANDLE CreateEvent(
  LPSECURITY_ATTRIBUTES lpEventAttributes, //安全属性
  BOOL                  bManualReset,   //事件重置/复位方式
  BOOL                  bInitialState, //事件初始状态
  LPCSTR                lpName  //为事件命名
);
  • 参数解释:
  • bManualReset为事件重置/复位方式,如果该参数被设置为TRUE那么就需要我们来手动重置事件对象,如果该参数被设置为FALSE,那么操纵系统会帮我们完成事件的重置和复位。
  • bInitialState:该参数指定了当创建事件后,该事件句柄是否处于有消息状态
  • 等候事件:
    WaitFor......函数
  • 触发事件(使事件句柄处于有消息状态)
BOOLSetEvent(
  HANDLE hEvent
);
  • 复位事件(将事件句柄设置为无消息状态)
BOOL ResetEvent(
  HANDLE hEvent
);
  • 关闭事件
    CloseHandle函数
    我们来看看事件的使用:
#include <stdio.h>
#include <windows.h>
DWORD WINAPI ThreadProc1(LPVOID lpParameter);
DWORD WINAPI ThreadProc2(LPVOID lpParameter);
DWORD g_value = 0;
HANDLE hEvent = NULL; //用于接收事件句柄
int main() {
  DWORD nID = 0;
  HANDLE hThread[2] = { 0 };
  hEvent = CreateEvent(NULL,FALSE,0,NULL);
  hThread[0] = CreateThread(NULL, 0, ThreadProc1, NULL, 0, &nID);
  hThread[1] = CreateThread(NULL, 0, ThreadProc2, NULL, 0, &nID);
  WaitForMultipleObjects(2, hThread, TRUE, INFINITE);
  printf("%d\n", g_value);
  CloseHandle(hEvent);
  return 0;
}
DWORD WINAPI ThreadProc1(LPVOID lpParameter) {
  char a[] = "********";
  while (1) {
    WaitForSingleObject(hEvent, INFINITE);
    for (int i = 0; i < strlen(a); i++) {
      printf("%c", a[i]);
    }
    printf("\n");
    ResetEvent(hEvent);
  }
  return 0;
}
DWORD WINAPI ThreadProc2(LPVOID lpParameter) {
  while (1) {
    Sleep(1000);
    SetEvent(hEvent);
  }
  return 0;
}

这是一个很典型的相互协调工作的双线程,我们在A线程中没有设定时间间隔,但是在B线程中设定了事件间隔,我们能够很明显地感受到输出是有时间间隔的:

四.信号量

  • 相关问题:
    类似于事件,解决线程之间通知的相关问题,但提供一个计数器,可以设置次数。
  • 创建信号量:
    使用CreateSemaphore函数:
    MSDN官方解释
HANDLE CreateSemaphore(
  LPSECURITY_ATTRIBUIES lpSemaphoreAttributes,         //安全属性
  LONG lInitialCount,        //初始化信号量数量
  LONG lMaximumCount,        //信号量的最大值
  LPSTSTR lpName             //为信号量命名
);创建成功返回信号量句柄
  • 等候信号量
    使用WaitFor...函数
    注意: 等候每通过一次,信号量的信号减一,知道为0阻塞
  • 给信号量指定定计数值
    使用ReleaseSemaphore()函数
    MSDN官方解释
BOOL ReleaseSemaphore(
  HANDLE hSeamephore,           //信号量句柄
  LONG lReleaseSemaphore,       //信号量将增加的量
  LPONG lpPreviousCount         //指向一个变量的指针,用于记录信号量的上一个计数
);
  • 关闭信号量:
    使用CloseHandle()函数
    我们来看看信号量的使用实例:
#include <stdio.h>
#include <windows.h>
DWORD WINAPI ThreadProc1(LPVOID lpParameter);
DWORD WINAPI ThreadProc2(LPVOID lpParameter);
HANDLE hSemaphore = NULL; //用于接收事件句柄
int main() {
  DWORD nID = 0;
  HANDLE hThread[2] = { 0 };
  hSemaphore = CreateSemaphore(NULL, 3, 10, NULL);
  hThread[0] = CreateThread(NULL, 0, ThreadProc1, NULL, 0, &nID);
  while (getchar()=='\n') {
    ReleaseSemaphore(hSemaphore, 5, NULL);
  }
  CloseHandle(hSemaphore);
  return 0;
}
  DWORD WINAPI ThreadProc1(LPVOID lpParameter) {
    char a[] = "********";
    while (1) {
      WaitForSingleObject(hSemaphore, INFINITE);
      for (int i = 0; i < strlen(a); i++) {
        printf("%c", a[i]);
      }
      printf("\n");
    }
    return 0;
  }

我们设置了计数器为3的信号量,我们发现程序最开始只会输出三行,每当我们按一次回车键,就将信号量计数值值为5:

本篇文章的分享就到这里,如果大家发现有错误之处,还请大家指出来,我会非常虚心地学习。希望我们共同进步!!!

相关文章
|
1月前
|
Java 数据库连接 数据库
不同业务使用同一个线程池发生死锁的技术探讨
【10月更文挑战第6天】在并发编程中,线程池是一种常用的优化手段,用于管理和复用线程资源,减少线程的创建和销毁开销。然而,当多个不同业务场景共用同一个线程池时,可能会引发一系列并发问题,其中死锁就是最为严重的一种。本文将深入探讨不同业务使用同一个线程池发生死锁的原因、影响及解决方案,旨在帮助开发者避免此类陷阱,提升系统的稳定性和可靠性。
47 5
|
30天前
|
监控 关系型数据库 MySQL
PowerShell 脚本编写 :自动化Windows 开发工作流程
PowerShell 脚本编写 :自动化Windows 开发工作流程
26 0
|
1月前
|
网络协议 安全 Java
难懂,误点!将多线程技术应用于Python的异步事件循环
难懂,误点!将多线程技术应用于Python的异步事件循环
61 0
|
1月前
|
Ubuntu Linux Python
如何利用wsl-Ubuntu里conda用来给Windows的PyCharm开发
如何在WSL(Windows Subsystem for Linux)的Ubuntu环境中使用conda虚拟环境来为Windows上的PyCharm开发设置Python解释器。
63 0
|
2月前
|
API Android开发 iOS开发
安卓与iOS开发中的线程管理对比
【9月更文挑战第12天】在移动应用的世界中,安卓和iOS平台各自拥有庞大的用户群体。开发者们在这两个平台上构建应用时,线程管理是他们必须面对的关键挑战之一。本文将深入探讨两大平台在线程管理方面的异同,通过直观的代码示例,揭示它们各自的设计理念和实现方式,帮助读者更好地理解如何在安卓与iOS开发中高效地处理多线程任务。
|
2月前
|
监控 Java
线程池中线程异常后:销毁还是复用?技术深度剖析
在并发编程中,线程池作为一种高效利用系统资源的工具,被广泛用于处理大量并发任务。然而,当线程池中的线程在执行任务时遇到异常,如何妥善处理这些异常线程成为了一个值得深入探讨的话题。本文将围绕“线程池中线程异常后:销毁还是复用?”这一主题,分享一些实践经验和理论思考。
129 3
|
2月前
|
存储 安全 程序员
Windows任务管理器开发原理与实现
Windows任务管理器开发原理与实现
|
3月前
|
vr&ar C# 图形学
WPF与AR/VR的激情碰撞:解锁Windows Presentation Foundation应用新维度,探索增强现实与虚拟现实技术在现代UI设计中的无限可能与实战应用详解
【8月更文挑战第31天】增强现实(AR)与虚拟现实(VR)技术正迅速改变生活和工作方式,在游戏、教育及工业等领域展现出广泛应用前景。本文探讨如何在Windows Presentation Foundation(WPF)环境中实现AR/VR功能,通过具体示例代码展示整合过程。尽管WPF本身不直接支持AR/VR,但借助第三方库如Unity、Vuforia或OpenVR,可实现沉浸式体验。例如,通过Unity和Vuforia在WPF中创建AR应用,或利用OpenVR在WPF中集成VR功能,从而提升用户体验并拓展应用功能边界。
68 0
|
3月前
|
开发者 C# Windows
WPF与游戏开发:当桌面应用遇见游戏梦想——利用Windows Presentation Foundation打造属于你的2D游戏世界,从环境搭建到代码实践全面解析新兴开发路径
【8月更文挑战第31天】随着游戏开发技术的进步,WPF作为.NET Framework的一部分,凭借其图形渲染能力和灵活的UI设计,成为桌面游戏开发的新选择。本文通过技术综述和示例代码,介绍如何利用WPF进行游戏开发。首先确保安装最新版Visual Studio并创建WPF项目。接着,通过XAML设计游戏界面,并在C#中实现游戏逻辑,如玩家控制和障碍物碰撞检测。示例展示了创建基本2D游戏的过程,包括角色移动和碰撞处理。通过本文,WPF开发者可更好地理解并应用游戏开发技术,创造吸引人的桌面游戏。
182 0
|
3月前
|
C# Windows 开发者
当WPF遇见OpenGL:一场关于如何在Windows Presentation Foundation中融入高性能跨平台图形处理技术的精彩碰撞——详解集成步骤与实战代码示例
【8月更文挑战第31天】本文详细介绍了如何在Windows Presentation Foundation (WPF) 中集成OpenGL,以实现高性能的跨平台图形处理。通过具体示例代码,展示了使用SharpGL库在WPF应用中创建并渲染OpenGL图形的过程,包括开发环境搭建、OpenGL渲染窗口创建及控件集成等关键步骤,帮助开发者更好地理解和应用OpenGL技术。
242 0