当前位置: 首页 > news >正文

WIN32核心编程 - 线程操作(二) 同步互斥

  • 公开视频 -> 链接点击跳转公开课程
  • 博客首页 -> 链接点击跳转博客主页

目录

竞态条件

CriticalSection

Mutex

CriticalSection & Mutex

Semaphore

Event


竞态条件

  • 多线程环境下,当多个线程同时访问或者修改同一个数据时,最终结果为线程执行的时许。

  • 如果没有同步机制,会发生竞态条件,可能导致数据不准确,或者程序发生异常等。

#include <iostream>
#include <windows.h>DWORD g_Num = 0;DWORD WINAPI WorkThread(LPVOID lp)
{for (size_t i = 0; i < 10000000; i++){//g_Num++;__asm LOCK INC [g_Num] }return 0;
}int main()
{HANDLE hThread[2] = { 0 };hThread[0] = CreateThread(NULL, 0, WorkThread, NULL, 0, NULL);hThread[1] = CreateThread(NULL, 0, WorkThread, NULL, 0, NULL);WaitForMultipleObjects(2, hThread, TRUE, -1);std::cout << g_Num << std::endl;return 0;
}

CriticalSection

#include <iostream>
#include <windows.h>DWORD g_Num = 0;
CRITICAL_SECTION cs = { 0 };DWORD WINAPI WorkThread(LPVOID lp)
{for (size_t i = 0; i < 1000000; i++){// 进入临界区EnterCriticalSection(&cs);// TODOg_Num++;// 退出临界区LeaveCriticalSection(&cs);}return 0;
}int main()
{HANDLE hThread[2] = { 0 };// 初始临界区InitializeCriticalSection(&cs);hThread[0] = CreateThread(NULL, 0, WorkThread, NULL, 0, NULL);hThread[1] = CreateThread(NULL, 0, WorkThread, NULL, 0, NULL);WaitForMultipleObjects(2, hThread, TRUE, -1);std::cout << g_Num << std::endl;// 清理临界区DeleteCriticalSection(&cs);return 0;
}

Mutex

  • 互斥体(Mutex),用于防止多个线程同时访问或修改共享资源。

  • 同一时刻下只有一个线程可以拥有互斥体的所有权,如果一个线程拥有了互斥体的所有权,则其他请求该互斥体的线程将会被阻塞,直到互斥体权限释放。

  • 创建互斥体 - CreateMutex

  • 请求互斥体 - WaitForSingleObject

  • 释放互斥体 - ReleaseMutex

#include <iostream>
#include <windows.h>HANDLE hMutex = 0;
DWORD g_Num = 0;DWORD WINAPI WorkThread(LPVOID lp)
{for (size_t i = 0; i < 100000; i++){WaitForSingleObject(hMutex, INFINITE);g_Num++;ReleaseMutex(hMutex);}return 0;
}int main()
{hMutex = CreateMutex(NULL, FALSE, NULL); HANDLE hThread1 = CreateThread(NULL, 0, WorkThread, NULL, 0, NULL);HANDLE hThread2 = CreateThread(NULL, 0, WorkThread, NULL, 0, NULL);WaitForSingleObject(hThread1, INFINITE);WaitForSingleObject(hThread2, INFINITE);CloseHandle(hThread1);CloseHandle(hThread2);CloseHandle(hMutex);std::cout << g_Num << std::endl;return 0;
}

CriticalSection & Mutex

  • 临界区

    • 共享资源的线程同步机制,临界区在同一进程的线程之间提供了互斥访问。

    • 每个线程在访问共享资源之前必须先能够进入临界区,在访问结束后离开临界区,完成线程同步。

  • 互斥体

    • 线程同步机制,用来限制多个线程同时访问共享资源。

    • 互斥体可以同步进程或者线程,且可以跨进程同步。
    • #include <iostream>
      #include <Windows.h>int main()
      {HANDLE hMutex = CreateMutex(NULL, FALSE, L"0xCC_Mutex");if (hMutex == NULL) return 0;if (GetLastError() == ERROR_ALREADY_EXISTS){MessageBox(NULL, L"禁止多开", L"错误", MB_OKCANCEL);return 0;}std::cout << "Game Start..." << std::endl;system("pause");CloseHandle(hMutex);return 0;
      }
  • 性能

    • 临界区在同一进程的线程中比互斥体更快。

  • 功能

    • 互斥体可以跨进程同步,但临界区只能够在同一个进程下的线程之间进行同步。

  • 所有权

    • 互斥体有严格的所有权要求,只有拥有互斥体权限的线程才能够释放它。

  • 死锁
    • 当线程在持有锁的情况下意外死亡(异常)
    • 如果线程在持有临界区锁的情况下意外终结,这个锁不会被释放,导致其他等待该临界区的线程无法正常执行,造成死锁。
    • #include <iostream>
      #include <Windows.h>CRITICAL_SECTION CriticalSection = { 0 };DWORD WINAPI WorkThread(LPVOID lp)
      {EnterCriticalSection(&CriticalSection);printf("TID -> %d \r\n", GetCurrentThreadId());Sleep(5000);LeaveCriticalSection(&CriticalSection);return 0;
      }int main()
      {InitializeCriticalSection(&CriticalSection);HANDLE hThread1 = CreateThread(NULL, 0, WorkThread, NULL, 0, NULL);Sleep(1000);TerminateThread(hThread1, 1);HANDLE hThread2 = CreateThread(NULL, 0, WorkThread, NULL, 0, NULL);WaitForSingleObject(hThread2, INFINITE);DeleteCriticalSection(&CriticalSection);return 0;
      }
    • 如果线程在持有互斥体锁的情况下意外终结,Windows会自动释放其所有权,使得其他线程可以继续正常执行。
    • #include <iostream>
      #include <Windows.h>HANDLE hMutex = NULL;DWORD WINAPI WorkThread1(LPVOID lp)
      {WaitForSingleObject(hMutex, INFINITE);printf("TID -> %d \r\n", GetCurrentThreadId());Sleep(5000);TerminateThread(GetCurrentThread(), -1);//todoreturn 0;
      }DWORD WINAPI WorkThread2(LPVOID lp)
      {printf("Wait For Thread1 Leave\r\n");WaitForSingleObject(hMutex, INFINITE);printf("TID -> %d \r\n", GetCurrentThreadId());ReleaseMutex(hMutex);return 0;
      }int main()
      {hMutex = CreateMutex(NULL, FALSE, NULL);HANDLE hThread1 = CreateThread(NULL, 0, WorkThread1, NULL, 0, NULL);Sleep(1000);HANDLE hThread2 = CreateThread(NULL, 0, WorkThread2, NULL, 0, NULL);WaitForSingleObject(hThread2, INFINITE);CloseHandle(hMutex);CloseHandle(hThread1);CloseHandle(hThread2);return 0;
      }

Semaphore

  • 信号量是一种同步对象,用于控制多个线程对共享资源的访问。它是一个计数器,用来表示可用资源的数量。当信号量的值大于0,它表示有资源可用;当值为0,表示没有可用资源。

    • 等待:试图减少信号量的值。如果信号量的值大于0,减1并继续执行。如果信号量的值为0,则线程阻塞,直到信号量的值变为大于0。

    • 释放:增加信号量的值。如果有其他线程因等待这个信号量而阻塞,它们中的一个将被唤醒。

  • 创建信号量

    • 在 Windows 系统中,使用 CreateSemaphoreCreateSemaphoreEx 函数创建信号量。

  • 等待(Wait)和释放(Release)信号量

    • 等待信号量通常使用 WaitForSingleObjectWaitForMultipleObjects 函数。

    • 释放信号量使用 ReleaseSemaphore 函数。

#include <iostream>
#include <Windows.h>#define MAX_COUNT_SEMAPHORE 3HANDLE g_SemapHore = NULL;
HANDLE g_hThreadArr[10] = { 0 };DWORD WINAPI WorkThread(LPVOID lp)
{WaitForSingleObject(g_SemapHore, INFINITE);for (size_t i = 0; i < 10; i++){std::cout << "COUNT -> " << (int)lp << std::endl;Sleep(500);}ReleaseSemaphore(g_SemapHore, 1, NULL);return 0;
}int main()
{g_SemapHore = CreateSemaphore(NULL,						//安全属性MAX_COUNT_SEMAPHORE,		//初始计数MAX_COUNT_SEMAPHORE,		//最大计数NULL						//信号名称);if (g_SemapHore == NULL){std::cout << GetLastError() << std::endl;return 1;}for (size_t i = 0; i < 10; i++){g_hThreadArr[i] = CreateThread(NULL,0,WorkThread,(LPVOID)i,0,NULL);}WaitForMultipleObjects(10, g_hThreadArr, TRUE, INFINITE);//closehandlereturn 0;
}

Event

  • 在Windows编程中,事件是一种同步机制,用于在多个线程之间发送信号。事件对象可以是手动重置自动重置

    • 手动重置事件(Manual Reset Event):当事件被设置(signaled)后,它将保持这个状态直到显式地被重置。这意味着多个等待该事件的线程都可以在事件被重置之前被唤醒。

    • 自动重置事件(Auto Reset Event):当事件被一个等待的线程接收(signaled)后,系统会自动将事件状态重置为非信号状态(non-signaled)。这意味着每次只允许一个线程被唤醒。

  • 创建事件

    • 使用Windows API函数CreateEvent可以创建一个事件对象

    • lpEventAttributes:指向安全属性的指针,如果设置为NULL,则使用默认安全性。

    • bManualReset:如果为TRUE,则创建一个手动重置事件,否则创建自动重置事件。

    • bInitialState:如果为TRUE,则初始状态为信号状态;如果为FALSE,则为非信号状态。

    • lpName:事件的名称。

  • 设置事件(将事件状态设置为信号状态)使用SetEvent函数

  • 重置事件(将事件状态设置为非信号状态)使用ResetEvent函数

  • 等待事件 等待一个事件对象变为信号状态使用WaitForSingleObject函数

#include <iostream>
#include <Windows.h>DWORD WINAPI WorkThread(LPVOID lp)
{HANDLE hEvent = *(HANDLE*)lp;std::cout << "Thread - " << GetCurrentThreadId() << " Waiting For Event" << std::endl;WaitForSingleObject(hEvent, INFINITE);std::cout << "Thread - " << GetCurrentThreadId() << " actived" << std::endl;return 0;
}int main()
{HANDLE hThreads[3] = { 0 };HANDLE hEvent = NULL;hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);if (hEvent == NULL) return 0;for (size_t i = 0; i < 3; i++){hThreads[i] = CreateThread(NULL, 0, WorkThread, &hEvent, 0, NULL);}Sleep(2000);SetEvent(hEvent);WaitForMultipleObjects(3, hThreads, TRUE, INFINITE);CloseHandle(hEvent);return 0;
}

相关文章:

WIN32核心编程 - 线程操作(二) 同步互斥

公开视频 -> 链接点击跳转公开课程博客首页 -> 链接点击跳转博客主页 目录 竞态条件 CriticalSection Mutex CriticalSection & Mutex Semaphore Event 竞态条件 多线程环境下&#xff0c;当多个线程同时访问或者修改同一个数据时&#xff0c;最终结果为线程执…...

web自动化(六)unittest 四大组件实战(京东登录搜索加入购物车)

Unittest框架 Unittest框架:框架测试模块测试管理模块测试统计模块&#xff0c;python的内置模块 import unittest Unittest框架四大组件: 1、TestCase 测试用例 2.TestFixture 测试用例夹具 测试用例需要执行的前置和后置 3.TestSuite 测试套件 把需要执行的测试用例汇总在一…...

鸿蒙语言基础类库:【@ohos.process (获取进程相关的信息)】

获取进程相关的信息 说明&#xff1a; 本模块首批接口从API version 7开始支持。后续版本的新增接口&#xff0c;采用上角标单独标记接口的起始版本。开发前请熟悉鸿蒙开发指导文档&#xff1a;gitee.com/li-shizhen-skin/harmony-os/blob/master/README.md点击或者复制转到。…...

华为笔试题

文章目录 1、数的分解2、字符串判断子串 1、数的分解 给定一个正整数n&#xff0c;如果能够分解为m(m > 1)个连续正整数之和&#xff0c; 请输出所有分解中&#xff0c;m最小的分解。 如果给定整数无法分解为连续正整数&#xff0c;则输出字符串"N"。 输入描述&a…...

【MySQL基础篇】函数及约束

1、函数 函数是指一段可以直接被另一段程序程序调用的程序或代码。 函数 - 字符串函数 MySQL中内置了很多字符串函数&#xff0c;常用的几个如下&#xff1a; 函数功能CONCAT(S1,S2,...,Sn)字符串拼接&#xff0c;将S1,S2,...,Sn拼接成一个字符串LOWER(str)将字符串str全部…...

YOLOv9报错:AttributeError: ‘list‘ object has no attribute ‘view‘

报错信息如下&#xff1a; red_distri, pred_scores torch.cat([xi.view(feats[0].shape[0], self.no, -1) for xi in feats], 2).split( AttributeError: ‘list’ object has no attribute ‘view’ 解决方法&#xff1a; 去yolov9/utils/loss_tal.py把167行代码更改&#…...

Bert入门-使用BERT(transformers库)对推特灾难文本二分类

Kaggle入门竞赛-对推特灾难文本二分类 这个是二月份学习的&#xff0c;最近整理资料所以上传到博客备份一下 数据在这里&#xff1a;https://www.kaggle.com/competitions/nlp-getting-started/data github&#xff08;jupyter notebook&#xff09;&#xff1a;https://gith…...

【DFS(深度优先搜索)详解】看这一篇就够啦

【DFS详解】看这一篇就够啦 &#x1f343;1. 算法思想&#x1f343;2. 三种枚举方式&#x1f343;2.1 指数型枚举&#x1f343;2.2 排列型枚举&#x1f343;2.3 组合型枚举 &#x1f343;3. 剪枝优化&#x1f343;4. 图的搜索&#x1f343;5. 来几道题试试手&#x1f343;5.1 选…...

java-spring boot光速入门教程(超详细!!)

目录 一、引言 1.1 初始化配置 1.2 整合第三方框架 1.3 后期维护 1.4 部署工程 1.5 敏捷式开发 二、SpringBoot介绍 spring boot 2.1 搭建一个spring boot工程 2.2 使用idea创建项目 2.3 在线创建姿势 2.4 项目的目录结构 2.5 项目的运行方式 2.6 yml文件格式 2…...

一、Prometheus和Grafana搭建

一、服务端Prometheus二进制安装 https://prometheus.io/下载过慢可使用迅雷下载 tar -zxvf prometheus-2.53.0.linux-amd64.tar.gz启动 ./prometheus --config.fileprometheus.yml将其配置为系统服务&#xff1a; vim /usr/lib/systemd/system/prometheus.service[Unit] D…...

从零开始的python学习生活

pycharm部分好用快捷键 变量名的定义 与之前学习过的语言有所不同的是&#xff0c;python中变量名的定义更加的简洁 such as 整形。浮点型和字符串的定义 money50 haha13.14 gaga"hello"字符串的定义依然是需要加上引号&#xff0c;也不需要写&#xff1b;了 字符…...

MSP学习

一、迁移资源调研 完成导入&#xff0c;类似完成选型分析 离线工具调研 账单 二、迁移计划 1、 ecs 确认开始构建迁移环境后&#xff0c;平台将锁定当前标记的迁移资源范围及源端、目标端资源配置信息&#xff0c;并以此为迁移环境构建及迁移实施的数据依据 目标账号…...

生产力工具|Endnote X9如何自动更新文件信息

一、以EndNote X9.2版本为例&#xff0c;打开EndNote文献管理软件。 二、在菜单栏找到“Edit→Preferences...”&#xff0c;点击打开&#xff0c;弹出一个“EndNote Preferences”窗口。 三、进行设置 在打开的窗口左侧选择“PDF Handing”&#xff0c;右边会出现自动导入文献…...

【python】字典、列表、集合综合练习

1、练习1(字典) 字典dic,dic {‘k1’:‘v1’, ‘k2’: ‘v2’, ‘k3’: [11,22,33]} (1). 请循环输出所有的key dic {"k1": "v1", "k2": "v2", "k3": [11, 22, 33]} for k in dic.keys():print(k)k1 k2 k3(2). 请循环输…...

超融合服务器挂载硬盘--linux系统

项目中需要增加服务器的硬盘容量&#xff0c;通过超融合挂载了硬盘后&#xff0c;还需要添加到指定的路径下&#xff0c;这里记录一下操作步骤。 一&#xff1a;通过管理界面挂载硬盘 这一步都是界面操作&#xff0c;登录超融合控制云台后&#xff0c;找到对应的服务器&#…...

Kafka如何防止消息重复发送

Kafka 提供了几种方式来防止消息重复发送和处理。这些方式通常取决于生产者和消费者的设置和实现方式&#xff1a; 生产者端幂等性&#xff08;什么是幂等性&#xff09;&#xff1a; 幂等性生产者&#xff1a;从 Kafka 0.11 版本开始引入了生产者端的幂等性支持。生产者可以通…...

数据库设计原则介绍

数据库设计是一个重要的过程&#xff0c;它涉及到创建一个逻辑结构来存储和管理数据。良好的数据库设计可以确保数据的完整性、一致性、性能和安全性。以下是一些关键的数据库设计原则&#xff1a; 1. 数据规范化 (Normalization) 目的&#xff1a;减少数据冗余、提高数据一致…...

反馈神经网络与不同类型的神经网络:BP神经网络,深度感知机,CNN,LSTM

反馈神经网络与不同类型的神经网络&#xff1a;BP神经网络&#xff0c;深度感知机&#xff0c;CNN&#xff0c;LSTM 在神经网络的研究和应用中&#xff0c;我们经常听到BP神经网络、深度感知机&#xff08;MLP&#xff09;、卷积神经网络&#xff08;CNN&#xff09;、长短期记…...

轮播图案例

丐版轮播图 <!DOCTYPE html> <html lang"zh-cn"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title> 基础轮播图 banner 移入移出</t…...

Spring 泛型依赖注入

Spring 泛型依赖注入&#xff0c;是利用泛型的优点对代码时行精简&#xff0c;将可重复使用的代码全部放到一个类之中&#xff0c;方便以后的维护和修改&#xff0c;同时在不增加代码的情况下增加代码的复用性。 示例代码&#xff1a; 创建实体类 Product package test.spri…...

C++ Linux调试(无IDE)

跨平台IDE编译调试C很方便&#xff0c;如QTCreate 、VSCode、Eclipse等&#xff0c;但是如果只能使用Shell控制台呢&#xff0c;gdb调试的优势就很明显了&#xff0c;在没有IDE的情况下&#xff0c;这个方式最有效。因为上手不是很难&#xff0c;特此整理 参考链接 目录 1、G…...

FFmpeg——视频拼接总结

最近需要做一个关于视频拼接的内容&#xff0c;需要将两个视频合成一个视频&#xff0c;使用opencv的话需要将视频读上来然后再写到文件了&#xff0c;这个会很消耗时间也没有必要。两个视频的编码格式是一样的&#xff0c;并不需要转码操作所以想法是直接将视频流补到后面&…...

springboot项目怎么样排除自带tomcat容器使用宝蓝德bes web中间件?

前言&#xff1a; 由于Spring Boot 1.x和2.x不兼容&#xff0c;BES提供了对应的Spring Boot Starter版本。 bes‑lite‑spring‑boot‑1.x‑starter.jar&#xff0c;适用于Spring Boot 1.x的版本。 bes‑lite‑spring‑boot‑2.x‑starter…...

响应式ref()和reactive()

文章目录 ref()reactive()ref对比reactivetoRefs与toRef ref() 作用&#xff1a;定义响应式变量。 语法&#xff1a;let xxxref(初始值)。 返回值&#xff1a;一个RefImpl的实例对象&#xff0c;简称ref对象或ref&#xff0c;ref对象的value属性是响应式的 注意点&#xff1…...

运维系列.Nginx中使用HTTP压缩功能

运维专题 Nginx中使用HTTP压缩功能 - 文章信息 - Author: 李俊才 (jcLee95) Visit me at CSDN: https://jclee95.blog.csdn.netMy WebSite&#xff1a;http://thispage.tech/Email: 291148484163.com. Shenzhen ChinaAddress of this article:https://blog.csdn.net/qq_28550…...

vue3项目图片压缩+rem+自动重启等plugin使用与打包配置

一、Svg配置 每次引入一张 SVG 图片都需要写一次相对路径&#xff0c;并且对 SVG 图片进行压缩优化也不够方便。 vite-svg-loader插件加载SVG文件作为Vue组件&#xff0c;使用SVGO进行优化。 插件网站https://www.npmjs.com/package/vite-svg-loader 1. 安装 pnpm i vite-svg…...

数据库性能优化系统设计

设计一个数据库性能优化系统&#xff0c;目标是监测、诊断并改善数据库的运行效率&#xff0c;确保系统能够高效稳定地处理大量数据请求。以下是一个概要设计&#xff0c;包括关键模块、功能和实现思路&#xff1a; 1. 系统架构 分布式监控中心&#xff1a;采用分布式架构收集…...

MyBatisPlus-分页插件的基本使用

目录 配置插件 使用分页API 配置插件 首先&#xff0c;要在配置类中注册MyBatisPlus的核心插件&#xff0c;同时添加分页插件。&#xff08;可以放到config软件包下&#xff09; 可以看到&#xff0c;我们定义了一个配置类&#xff0c;在配置类里声明了一个Bean,这个Bean的名…...

深入探索Python库的奇妙世界:赋能编程的无限可能

在编程的浩瀚宇宙中&#xff0c;Python以其简洁的语法、强大的功能和广泛的应用领域&#xff0c;成为了众多开发者心中的璀璨明星。而Python之所以能够如此耀眼&#xff0c;很大程度上得益于其背后庞大的库生态系统。这些库&#xff0c;如同一块块精心雕琢的积木&#xff0c;让…...

力扣爆刷第161天之TOP100五连刷71-75(搜索二叉树、二维矩阵、路径总和)

力扣爆刷第161天之TOP100五连刷71-75&#xff08;搜索二叉树、二维矩阵、路径总和&#xff09; 文章目录 力扣爆刷第161天之TOP100五连刷71-75&#xff08;搜索二叉树、二维矩阵、路径总和&#xff09;一、98. 验证二叉搜索树二、394. 字符串解码三、34. 在排序数组中查找元素的…...