当前位置: 首页 > 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…...

逻辑回归:给不确定性划界的分类大师

想象你是一名医生。面对患者的检查报告&#xff08;肿瘤大小、血液指标&#xff09;&#xff0c;你需要做出一个**决定性判断**&#xff1a;恶性还是良性&#xff1f;这种“非黑即白”的抉择&#xff0c;正是**逻辑回归&#xff08;Logistic Regression&#xff09;** 的战场&a…...

Oracle查询表空间大小

1 查询数据库中所有的表空间以及表空间所占空间的大小 SELECTtablespace_name,sum( bytes ) / 1024 / 1024 FROMdba_data_files GROUP BYtablespace_name; 2 Oracle查询表空间大小及每个表所占空间的大小 SELECTtablespace_name,file_id,file_name,round( bytes / ( 1024 …...

Objective-C常用命名规范总结

【OC】常用命名规范总结 文章目录 【OC】常用命名规范总结1.类名&#xff08;Class Name)2.协议名&#xff08;Protocol Name)3.方法名&#xff08;Method Name)4.属性名&#xff08;Property Name&#xff09;5.局部变量/实例变量&#xff08;Local / Instance Variables&…...

Keil 中设置 STM32 Flash 和 RAM 地址详解

文章目录 Keil 中设置 STM32 Flash 和 RAM 地址详解一、Flash 和 RAM 配置界面(Target 选项卡)1. IROM1(用于配置 Flash)2. IRAM1(用于配置 RAM)二、链接器设置界面(Linker 选项卡)1. 勾选“Use Memory Layout from Target Dialog”2. 查看链接器参数(如果没有勾选上面…...

苍穹外卖--缓存菜品

1.问题说明 用户端小程序展示的菜品数据都是通过查询数据库获得&#xff0c;如果用户端访问量比较大&#xff0c;数据库访问压力随之增大 2.实现思路 通过Redis来缓存菜品数据&#xff0c;减少数据库查询操作。 缓存逻辑分析&#xff1a; ①每个分类下的菜品保持一份缓存数据…...

Cloudflare 从 Nginx 到 Pingora:性能、效率与安全的全面升级

在互联网的快速发展中&#xff0c;高性能、高效率和高安全性的网络服务成为了各大互联网基础设施提供商的核心追求。Cloudflare 作为全球领先的互联网安全和基础设施公司&#xff0c;近期做出了一个重大技术决策&#xff1a;弃用长期使用的 Nginx&#xff0c;转而采用其内部开发…...

C++ 求圆面积的程序(Program to find area of a circle)

给定半径r&#xff0c;求圆的面积。圆的面积应精确到小数点后5位。 例子&#xff1a; 输入&#xff1a;r 5 输出&#xff1a;78.53982 解释&#xff1a;由于面积 PI * r * r 3.14159265358979323846 * 5 * 5 78.53982&#xff0c;因为我们只保留小数点后 5 位数字。 输…...

Spring AI与Spring Modulith核心技术解析

Spring AI核心架构解析 Spring AI&#xff08;https://spring.io/projects/spring-ai&#xff09;作为Spring生态中的AI集成框架&#xff0c;其核心设计理念是通过模块化架构降低AI应用的开发复杂度。与Python生态中的LangChain/LlamaIndex等工具类似&#xff0c;但特别为多语…...

MySQL JOIN 表过多的优化思路

当 MySQL 查询涉及大量表 JOIN 时&#xff0c;性能会显著下降。以下是优化思路和简易实现方法&#xff1a; 一、核心优化思路 减少 JOIN 数量 数据冗余&#xff1a;添加必要的冗余字段&#xff08;如订单表直接存储用户名&#xff09;合并表&#xff1a;将频繁关联的小表合并成…...

MySQL 8.0 事务全面讲解

以下是一个结合两次回答的 MySQL 8.0 事务全面讲解&#xff0c;涵盖了事务的核心概念、操作示例、失败回滚、隔离级别、事务性 DDL 和 XA 事务等内容&#xff0c;并修正了查看隔离级别的命令。 MySQL 8.0 事务全面讲解 一、事务的核心概念&#xff08;ACID&#xff09; 事务是…...