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

Windows多线程编程 互斥量和临界区使用

Windows 多线程编程允许程序同时运行多个线程,提高程序的并发性和执行效率。多线程编程中的核心概念包括线程的创建、同步、调度、数据共享和竞争条件等。本文详细介绍了 Windows 多线程编程的关键技术点,并解释如何使用线程同步机制来保证线程安全。

1. 线程基础概念

1.1 线程

线程是操作系统能够独立调度的最小执行单元。一个进程可以包含多个线程,这些线程共享进程的地址空间和资源。多线程编程通过并发执行多个线程,提升程序性能,特别是在 I/O 操作、网络请求或图像处理等任务中。

1.2 进程 vs. 线程

进程:程序在操作系统中的运行实例。每个进程有独立的地址空间和资源。
线程:线程是进程中的轻量级执行单元,多个线程可以共享进程的内存和资源。一个进程至少包含一个主线程,可以派生出多个子线程。

2. 线程的创建与管理

在 Windows 中,创建和管理线程可以通过 WinAPI 提供的多种方法,其中常用的是 CreateThread 和 C++11 提供的标准库线程类。

2.1 使用 CreateThread

这是 WinAPI 中直接用于创建线程的函数,它返回一个线程句柄,用于管理线程。

#include <windows.h>
#include <iostream>// 线程函数
DWORD WINAPI ThreadFunc(LPVOID lpParam) {for (int i = 0; i < 5; i++) {std::cout << "Thread running...\n";Sleep(1000); // 模拟工作,暂停1秒}return 0;
}int main() {HANDLE hThread = CreateThread(NULL,            // 默认安全属性0,               // 默认堆栈大小ThreadFunc,      // 线程函数NULL,            // 参数传递给线程函数0,               // 默认创建标志NULL             // 可选的线程ID);if (hThread == NULL) {std::cout << "Error: Unable to create thread\n";return 1;}// 等待线程结束WaitForSingleObject(hThread, INFINITE);// 关闭线程句柄CloseHandle(hThread);return 0;
}

2.2 使用 C++11 std::thread

现代 C++ 提供了跨平台的 std::thread 类,用来简化线程的创建和管理。

#include <iostream>
#include <thread>void ThreadFunc() {for (int i = 0; i < 5; i++) {std::cout << "Thread running...\n";std::this_thread::sleep_for(std::chrono::seconds(1));  // 模拟工作}
}int main() {std::thread t(ThreadFunc);  // 创建线程t.join();  // 等待线程结束return 0;
}

3. 线程同步

在多线程程序中,多个线程可能会同时访问共享资源(如内存、文件等),如果不加以控制,可能会导致数据竞态条件(Race Condition)。线程同步用于协调线程对共享资源的访问,避免数据冲突。

  • 常用的同步机制包括:
临界区(Critical Section)
互斥量(Mutex)
信号量(Semaphore)
事件(Event)

3.1 临界区(Critical Section)

临界区是一种轻量级的同步机制,仅适用于单进程的线程同步。临界区在同一时间只允许一个线程进入,其他线程必须等待当前线程离开临界区后才能进入。

#include <windows.h>
#include <iostream>CRITICAL_SECTION criticalSection;  // 定义临界区void ThreadFunc() {EnterCriticalSection(&criticalSection);  // 进入临界区std::cout << "Thread ID: " << GetCurrentThreadId() << " is working.\n";LeaveCriticalSection(&criticalSection);  // 离开临界区
}int main() {InitializeCriticalSection(&criticalSection);  // 初始化临界区HANDLE hThread1 = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ThreadFunc, NULL, 0, NULL);HANDLE hThread2 = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ThreadFunc, NULL, 0, NULL);WaitForSingleObject(hThread1, INFINITE);WaitForSingleObject(hThread2, INFINITE);DeleteCriticalSection(&criticalSection);  // 删除临界区return 0;
}

3.2 互斥量(Mutex)

互斥量可以在多个线程甚至多个进程之间同步访问共享资源。与临界区相比,互斥量开销较大,但功能更强。

#include <windows.h>
#include <iostream>HANDLE hMutex;void ThreadFunc() {WaitForSingleObject(hMutex, INFINITE);  // 获取互斥量std::cout << "Thread ID: " << GetCurrentThreadId() << " is working.\n";ReleaseMutex(hMutex);  // 释放互斥量
}int main() {hMutex = CreateMutex(NULL, FALSE, NULL);  // 创建互斥量HANDLE hThread1 = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ThreadFunc, NULL, 0, NULL);HANDLE hThread2 = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ThreadFunc, NULL, 0, NULL);WaitForSingleObject(hThread1, INFINITE);WaitForSingleObject(hThread2, INFINITE);CloseHandle(hMutex);  // 关闭互斥量句柄return 0;
}

3.3 信号量(Semaphore)

信号量允许多个线程访问同一资源,信号量内部有一个计数器,控制同时访问的线程数量。当计数器减为 0 时,其他线程必须等待。

#include <windows.h>
#include <iostream>HANDLE hSemaphore;void ThreadFunc() {WaitForSingleObject(hSemaphore, INFINITE);  // 等待信号量std::cout << "Thread ID: " << GetCurrentThreadId() << " is working.\n";ReleaseSemaphore(hSemaphore, 1, NULL);  // 释放信号量
}int main() {hSemaphore = CreateSemaphore(NULL, 2, 2, NULL);  // 最大允许2个线程同时执行HANDLE hThread1 = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ThreadFunc, NULL, 0, NULL);HANDLE hThread2 = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ThreadFunc, NULL, 0, NULL);HANDLE hThread3 = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ThreadFunc, NULL, 0, NULL);WaitForSingleObject(hThread1, INFINITE);WaitForSingleObject(hThread2, INFINITE);WaitForSingleObject(hThread3, INFINITE);CloseHandle(hSemaphore);return 0;
}

3.4 事件(Event)

事件用于在线程之间传递信号,某个线程可以等待事件的状态(有信号或无信号),然后作出相应动作。事件可以用来实现线程之间的通知机制。

#include <windows.h>
#include <iostream>HANDLE hEvent;DWORD WINAPI ThreadFunc(LPVOID lpParam) {std::cout << "Thread waiting for event...\n";WaitForSingleObject(hEvent, INFINITE);  // 等待事件std::cout << "Thread received event signal!\n";return 0;
}int main() {hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);  // 创建事件HANDLE hThread = CreateThread(NULL, 0, ThreadFunc, NULL, 0, NULL);Sleep(2000);  // 模拟工作SetEvent(hEvent);  // 触发事件WaitForSingleObject(hThread, INFINITE);CloseHandle(hEvent);return 0;
}

4. 线程同步中的问题

4.1 死锁

死锁是指两个或多个线程在等待彼此持有的资源,导致线程永远无法继续执行。避免死锁的方法:

使用一致的锁顺序:所有线程获取锁的顺序要一致。
避免嵌套锁定:尽量避免一个线程在持有一个锁的同时请求另一个锁。

4.2 竞争条件

竞争条件发生在多个线程同时读取或写入共享数据时,由于执行顺序的不确定性,可能导致错误结果。解决方法是使用合适的同步机制(如临界区、互斥量等)来保护共享数据的访问。

5、Window线程和临界封装

1、线程XThread

1、XThread.h
#pragma once#ifdef  XPLATFORM_EXPORTS
#define XPLATFORM_API __declspec(dllexport)
#else
#define XPLATFORM_API __declspec(dllimport)
#endifclass XPLATFORM_API XThread
{
public:XThread();virtual ~XThread();bool Start();virtual void Run() = 0;void Wait();void Suspend();void Resume();
private:unsigned int thId = 0;
};
2、XThread.cpp
#include "XThread.h"
#include <process.h>
#include <Windows.h>XThread::XThread()
{}
XThread::~XThread()
{
}
static void ThreadMain(void *para)
{XThread* th = (XThread*)para;if(th == nullptr) return;th->Run();_endthread();
}
bool XThread::Start()
{thId = _beginthread(ThreadMain, 0, this);return thId <= 0;
}
void XThread::Wait()
{if(thId <= 0) return;WaitForSingleObject((HANDLE)thId, INFINITE);
}
void XThread::Suspend()
{if (thId <= 0) return;SuspendThread((HANDLE)thId);
}
void XThread::Resume()
{if (thId <= 0) return;ResumeThread((HANDLE)thId);
}

2、临界区封装

1、XMutex.h
#pragma once
#ifdef  XPLATFORM_EXPORTS
#define XPLATFORM_API __declspec(dllexport)
#else
#define XPLATFORM_API __declspec(dllimport)
#endif
class XPLATFORM_API XMutex
{
public:XMutex();~XMutex();void Lock();void UnLock();
private:void* section = nullptr;
};
2、XMutex.cpp
#include "XMutex.h"
#include <windows.h>XMutex::XMutex()
{this->section = new CRITICAL_SECTION();if (section == nullptr) return;InitializeCriticalSection((LPCRITICAL_SECTION)this->section);
}XMutex::~XMutex()
{CRITICAL_SECTION *critical_section = (LPCRITICAL_SECTION)this->section;if(critical_section == nullptr) return;delete critical_section;
}void XMutex::Lock()
{if (section == nullptr) return;EnterCriticalSection((LPCRITICAL_SECTION)this->section);
}void XMutex::UnLock()
{if(section == nullptr) return;LeaveCriticalSection((LPCRITICAL_SECTION)this->section);
}

相关文章:

Windows多线程编程 互斥量和临界区使用

Windows 多线程编程允许程序同时运行多个线程&#xff0c;提高程序的并发性和执行效率。多线程编程中的核心概念包括线程的创建、同步、调度、数据共享和竞争条件等。本文详细介绍了 Windows 多线程编程的关键技术点&#xff0c;并解释如何使用线程同步机制来保证线程安全。 1…...

Java中集合类型的转换

在Java编程中&#xff0c;集合框架&#xff08;Collections Framework&#xff09;提供了一套用于存储和处理对象集合的接口和类。由于集合框架的灵活性和强大功能&#xff0c;我们经常需要在不同的集合类型之间进行转换。本文将介绍Java中常见的集合类型转换方法&#xff0c;包…...

汽车售后TPMS浅谈

汽车售后中的TPMS&#xff0c;即轮胎压力监测系统&#xff08;Tire Pressure Monitoring System&#xff09;&#xff0c;是一种重要的汽车安全系统。以下是对汽车售后TPMS的详细解释&#xff1a; 一、TPMS的作用 TPMS的主要作用是在汽车行驶过程中对轮胎气压进行实时自动监测…...

LUCEDA IPKISS Tutorial 77:在版图一定范围内填充dummy

案例分享&#xff1a;在给定的Shape内填充dummy 所有代码如下&#xff1a; from si_fab import all as pdk from ipkiss3 import all as i3 from shapely.geometry import Polygon, MultiPolygon import numpy as np import matplotlib.pyplot as pltclass CellFilledWithCon…...

TON生态小游戏开发:推广、经济模型与UI设计的建设指南

随着区块链技术的快速发展&#xff0c;基于区块链的Web3游戏正引领行业变革。而TON生态小游戏&#xff0c;借助Telegram庞大的用户基础和TON&#xff08;The Open Network&#xff09;链上技术&#xff0c;已成为这一领域的明星之一。国内外开发者正迅速涌入&#xff0c;开发和…...

Python 量子机器学习:基础概念、关键算法与应用实践

&#x1f31f; Python 量子机器学习&#xff1a;基础概念、关键算法与应用实践 目录 &#x1f30d; 量子计算的基本原理 量子位、叠加、纠缠等概念解析量子计算如何影响机器学习&#xff1a;速度与效率的提升 &#x1f680; 量子机器学习中的关键算法 量子支持向量机&#xf…...

信息安全数学基础(29) x^2 + y^2 = p

前言 方程 x2y2p 是一个涉及整数解和素数 p 的二次方程。这个方程在数论和几何中都有重要的意义&#xff0c;特别是在研究圆的整数点和费马大定理的背景下。 一、定义与背景 方程 x2y2p 表示一个平面上的圆&#xff0c;其圆心在原点 (0,0)&#xff0c;半径为 p​&#xff08;当…...

ChatGPT国内中文版镜像网站整理合集(2024/10/06)

一、GPT中文镜像站 ① yixiaai.com 支持GPT4、4o以及o1&#xff0c;支持MJ绘画 ② chat.lify.vip 支持通用全模型&#xff0c;支持文件读取、插件、绘画、AIPPT ③ AI Chat 支持GPT3.5/4&#xff0c;4o以及MJ绘画 1. 什么是镜像站 镜像站&#xff08;Mirror Site&#xff…...

图文深入理解Oracle DB Scheduler

值此国庆佳节&#xff0c;深宅家中&#xff0c;闲来无事&#xff0c;就多写几篇博文。今天继续宅继续写。本篇图文深入介绍Oracle DB Scheduler。 Oracle为什么要使Scheduler&#xff1f; 答案就是6个字&#xff1a;简化管理任务。 • Scheduler&#xff08;调度程序&#x…...

gin如何具体利用Server-Send-Events(SSE)实时推送技术实现消息推送

目录 业务场景 解决方案 1. 轮询 2. WebSocket 3. SSE(Server-Send-Events) 代码实现 总结 业务场景 在抖音、美团等APP中&#xff0c;我们经常会遇到APP内部的消息推送&#xff0c;如关注的人的动态消息推送、点赞评论互动消息推送以及算法推荐消息推送。这些场景都是…...

写端口-tcp udp不同方式发包和接包

最近一直在学习网络编程&#xff0c;今天把 socket部分做一个总结。 Python 的socket库可以实现不同协议不同地址的发包和收包&#xff0c;无奈资料很少&#xff0c;官方例子有限&#xff0c;大神博客很少提及&#xff0c; 经过一番尝试后&#xff0c;总结以下几点用法以便大家…...

计算机的错误计算(一百二十)

摘要 探讨在许多应用中出现的函数 的计算精度问题。 例1. 考虑在许多应用中出现的函数 计算 不妨在Python下计算&#xff1a; 若用下列Rust代码在线计算&#xff1a; fn f(x: f64) -> f64 {(x.exp() - 1.0) / x }fn main() {let result f(0.9e-13);println!("…...

Spring Boot 中使用 JSON Schema 来校验复杂 JSON 数据

​ 博客主页: 南来_北往 系列专栏&#xff1a;Spring Boot实战 在现代软件开发中&#xff0c;尤其是构建 RESTful API 时&#xff0c;处理 JSON 数据已成为一项基本任务。JSON&#xff08;JavaScript Object Notation&#xff09;因其轻量级和易于人类阅读的特点&#xff…...

QT实现Opencv图像处理

案例 基于QT的人脸识别 pro文件需要加以下代码 INCLUDEPATH E:/opencv/opencv3.4-qt-intall/install/include INCLUDEPATH E:/opencv/opencv3.4-qt-intall/install/include/opencv INCLUDEPATH E:/opencv/opencv3.4-qt-intall/install/include/opencv2 LIBS E:/opencv/o…...

刚转Mac的新手如何卸载不需要的应用程序

最开始转Mac系统的时候很是苦恼&#xff0c;到底该怎么卸载App啊&#xff0c;App直接拖到废纸篓真的能卸载干净吗&#xff0c;卸载App时会不会留下一些文件残留&#xff0c;慢慢的会不会占满内存&#xff0c;于是我找到了一个免费的卸载工具——XApp。 这是一款Mac应用程序卸载…...

Unity 3d 继承MonoBahaviour的单例

在使用Unity3d开发游戏或做客户端项目时&#xff0c;单例是最常见的模式之一&#xff0c;他简单了类的创建&#xff0c;在代码中可以直接调用。下面是两个例子&#xff0c;代码两种不同类型的单例&#xff0c;一个是基本类的单例基类&#xff0c;不是unity MonoBehaviour的类都…...

grafana version 11.1.0 设置Y轴刻度为1

grafana 版本 # /usr/share/grafana/bin/grafana --version grafana version 11.1.0设置轴 Axis 搜索 Standard options 在"Decimals"中输入0&#xff0c;确保只显示整数...

Elasticsearch的安装与配置

注意&#xff1a;elasticsearch 禁止安装在/root路径下&#xff01; 1、创建用户组 groupadd elastic 2、创建用户 useradd es -d /home/es -g elastic echo es | passwd es --stdin 3、给新创建的用户进行授权 chown -R es:elastic /home/es chmod -R 775 /home/es 4…...

win0删除 Windows.old

参考&#xff1a;https://blog.csdn.net/xitongzhijia_abc/article/details/126270452 win10如下所示&#xff1a; 打开 设置–>系统—>存储...

常见IDE及其编译器的讲解

IDE 意思是&#xff1a;集成开发环境 常见的IDE有哪些&#xff1f; eg. devC,VS2022,xcode,codeblocks,clion常见编译器有哪些&#xff1f; eg.msvc,gcc,clang微软的底层编译器是msvc苹果的底层编译器是clang IDE编译器特点devC集成了gcc小巧&#xff0c;工具简单&…...

关于iview组件中使用 table , 绑定序号分页后序号从1开始的解决方案

问题描述&#xff1a;iview使用table 中type: "index",分页之后 &#xff0c;索引还是从1开始&#xff0c;试过绑定后台返回数据的id, 这种方法可行&#xff0c;就是后台返回数据的每个页面id都不完全是按照从1开始的升序&#xff0c;因此百度了下&#xff0c;找到了…...

什么是Ansible Jinja2

理解 Ansible Jinja2 模板 Ansible 是一款功能强大的开源自动化工具&#xff0c;可让您无缝地管理和配置系统。Ansible 的一大亮点是它使用 Jinja2 模板&#xff0c;允许您根据变量数据动态生成文件、配置设置和脚本。本文将向您介绍 Ansible 中的 Jinja2 模板&#xff0c;并通…...

Maven 概述、安装、配置、仓库、私服详解

目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...

基于Java Swing的电子通讯录设计与实现:附系统托盘功能代码详解

JAVASQL电子通讯录带系统托盘 一、系统概述 本电子通讯录系统采用Java Swing开发桌面应用&#xff0c;结合SQLite数据库实现联系人管理功能&#xff0c;并集成系统托盘功能提升用户体验。系统支持联系人的增删改查、分组管理、搜索过滤等功能&#xff0c;同时可以最小化到系统…...

[ACTF2020 新生赛]Include 1(php://filter伪协议)

题目 做法 启动靶机&#xff0c;点进去 点进去 查看URL&#xff0c;有 ?fileflag.php说明存在文件包含&#xff0c;原理是php://filter 协议 当它与包含函数结合时&#xff0c;php://filter流会被当作php文件执行。 用php://filter加编码&#xff0c;能让PHP把文件内容…...

AI语音助手的Python实现

引言 语音助手(如小爱同学、Siri)通过语音识别、自然语言处理(NLP)和语音合成技术,为用户提供直观、高效的交互体验。随着人工智能的普及,Python开发者可以利用开源库和AI模型,快速构建自定义语音助手。本文由浅入深,详细介绍如何使用Python开发AI语音助手,涵盖基础功…...

Linux部署私有文件管理系统MinIO

最近需要用到一个文件管理服务&#xff0c;但是又不想花钱&#xff0c;所以就想着自己搭建一个&#xff0c;刚好我们用的一个开源框架已经集成了MinIO&#xff0c;所以就选了这个 我这边对文件服务性能要求不是太高&#xff0c;单机版就可以 安装非常简单&#xff0c;几个命令就…...

门静脉高压——表现

一、门静脉高压表现 00:01 1. 门静脉构成 00:13 组成结构&#xff1a;由肠系膜上静脉和脾静脉汇合构成&#xff0c;是肝脏血液供应的主要来源。淤血后果&#xff1a;门静脉淤血会同时导致脾静脉和肠系膜上静脉淤血&#xff0c;引发后续系列症状。 2. 脾大和脾功能亢进 00:46 …...

leetcode_69.x的平方根

题目如下 &#xff1a; 看到题 &#xff0c;我们最原始的想法就是暴力解决: for(long long i 0;i<INT_MAX;i){if(i*ix){return i;}else if((i*i>x)&&((i-1)*(i-1)<x)){return i-1;}}我们直接开始遍历&#xff0c;我们是整数的平方根&#xff0c;所以我们分两…...

raid存储技术

1. 存储技术概念 数据存储架构是对数据存储方式、存储设备及相关组件的组织和规划&#xff0c;涵盖存储系统的布局、数据存储策略等&#xff0c;它明确数据如何存储、管理与访问&#xff0c;为数据的安全、高效使用提供支撑。 由计算机中一组存储设备、控制部件和管理信息调度的…...