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

C++ 多线程(三)

C++ 多线程(三)

  • 一、Windows创建线程
  • 二、Windows互斥锁
  • 三、windows挂起和唤醒线程
  • 四、简单架构Runnable
  • 五、线程命名修改


一、Windows创建线程

我们先来看一下创建windows线程的API

WINBASEAPI
_Ret_maybenull_
HANDLE
WINAPI
CreateThread(_In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes,_In_ SIZE_T dwStackSize,_In_ LPTHREAD_START_ROUTINE lpStartAddress,_In_opt_ __drv_aliasesMem LPVOID lpParameter,_In_ DWORD dwCreationFlags,_Out_opt_ LPDWORD lpThreadId);

以下是形参的具体用途
lpThreadAttributes 线程安全有关,一般传入null
dwStackSize 分配的空间大小,0为自动分配
lpStartAddress 需要在线程中执行的函数
lpParameter 传入的参数
dwCreationFlags 控制线程的标准,0为一开始就执行,#define CREATE_SUSPENDED 0x00000004 为开始挂起
lpThreadId 线程的id

定义在window线程中执行的函数

DWORD WINAPI FuncThread(LPVOID lpParam)
{Sleep(1000);std::cout << "Hello World" << std::endl;return 0l;
}

创建windows线程,注意使用完毕后要CloseHandle。
windows的一些操作都要使用CloseHandle

	HANDLE h = CreateThread(nullptr, 0, FuncThread, nullptr, 0, nullptr);Sleep(2000);CloseHandle(h);

二、Windows互斥锁

WINBASEAPI
_Ret_maybenull_
HANDLE
WINAPI
CreateMutexW(_In_opt_ LPSECURITY_ATTRIBUTES lpMutexAttributes,_In_ BOOL bInitialOwner,_In_opt_ LPCWSTR lpName);

lpMutexAttributes 线程安全有关,一般传入null
bInitialOwner 有没有该锁的控制权
lpName 锁的名称

WaitForSingleObject 是类似lock一样的上锁,后面的参数为等待的时间
ReleaseMutex(WindowMu) 是类似unlock的功能,释放这个锁

DWORD WINAPI Func01(LPVOID Params)
{WaitForSingleObject(WindowMu, INFINITE);std::cout << "Hello World" << std::endl;ReleaseMutex(WindowMu);return 0;
}

下面是使用案例

	WindowMu = CreateMutex(nullptr, false, L"TestLock");WaitForSingleObject(WindowMu, INFINITE);HANDLE h = CreateThread(nullptr, 0, Func01, nullptr, 0, nullptr);Sleep(5000);ReleaseMutex(WindowMu);Sleep(2000);

三、windows挂起和唤醒线程

和之前的std的线程一样都是使用一样的api

这个是挂起线程

	SuspendThread(h);

这个是唤醒线程

	ResumeThread(h);

四、简单架构Runnable

为了更方便的使用多线程,UE中有Runnable,仿造UE的实现,实现一个简易版本的
主要文件有三个Runnable、RunnableThread、Platform
在这里插入图片描述
Runnable.h

#pragma onceclass RunnableThread;
class Runnable
{
public:Runnable();virtual bool Init();virtual int Run();virtual int Stop();virtual bool Exit();
protected:virtual int Run_Func() = 0;bool bStop = false;RunnableThread* Thread;
};

Runnable.cpp

#include "Runnable.h"
#include "Platform.h"Runnable::Runnable()
{Thread = Platform::Create(this);
}bool Runnable::Init()
{return true;
}int Runnable::Run()
{for(;;){while (!bStop){Run_Func();Platform::Sleep(100);}Exit();break;}return 0;
}int Runnable::Stop()
{if (!bStop) {bStop = true;}return 0;
}bool Runnable::Exit()
{return true;
}

RunnableThread.h

#pragma once
#include "Runnable.h"
class RunnableThread
{
public:RunnableThread();virtual bool Create(Runnable* Runnable) = 0;
};

RunnableThread.cpp

#include "RunnableThread.h"RunnableThread::RunnableThread()
{
}

Platform.h

#pragma onceclass Runnable;
class RunnableThread;typedef unsigned long SLEEP_TIME;class Platform
{
public:static RunnableThread* Create(Runnable* Runnable);static void Sleep(SLEEP_TIME SpTime);
};

Platform.cpp

class WindowsRunnableThread : public RunnableThread
{
protected:HANDLE ThreadHandle;
public:bool Create(Runnable* InRunnable) override{auto ThreadFunc = [](LPVOID Params) -> DWORD{Runnable* runnable = (Runnable*)Params;if (runnable){DWORD ReturnValue = runnable->Run();return ReturnValue;}return 0;};ThreadHandle = CreateThread(nullptr, 0, ThreadFunc, InRunnable, 0, nullptr);return true;}~WindowsRunnableThread(){CloseHandle(ThreadHandle);delete ThreadHandle;}
};class LinuxRunnableThread : public RunnableThread
{bool Create(Runnable* Runnable) override{return false;}
};RunnableThread* Platform::Create(Runnable* Runnable)
{RunnableThread* Thread = nullptr;if (Runnable){if (Runnable->Init()){
#if _WIN32Thread = new WindowsRunnableThread();
#elif __linux__Thread = new LinuxRunnableThread();
#endifif (Thread->Create(Runnable)) {return Thread;}else {delete Thread;return nullptr;}}}return Thread;
}void Platform::Sleep(SLEEP_TIME SpTime)
{
#if _WIN32::Sleep(SpTime);
#elif __linux__
#endif
}
  • RunnableThread:对线程进行封装的接口,具体平台的线程需要继承此接口进行具体的线程创建。
  • Runnable:有关具体需要在线程中执行的函数的声明周期。
  • Platform:创建具体平台对应的线程,类似工厂。

五、线程命名修改

我们创建的子线程名称是系统自动生成的,如果我们需要自己修改创建的名称该如何处理?
一种老式的固定写法(调试器可见)

struct FThreadInfo
{DWORD dwType;LPCSTR szName;DWORD dwThreadID;DWORD dwFlags;
};FThreadInfo ThreadInfo;
ThreadInfo.dwType = 0x1000;
ThreadInfo.szName = runnable->GetThread()->GetThreadName();
ThreadInfo.dwThreadID = GetCurrentThreadId();
ThreadInfo.dwFlags = 0;__try
{RaiseException(0x406D1388, 0, sizeof(ThreadInfo) / sizeof(DWORD), (ULONG_PTR*)(&ThreadInfo));
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
}
http://www.dtcms.com/a/315678.html

相关文章:

  • 嵌入式学习的第四十三天-ds18b20 数字温度传感器
  • 如何在nuxtjs项目中使用vuex?
  • duxapp中主题系统是如何实现动态切换的
  • Redis 基础(一)
  • 数字图像处理(冈萨雷斯)第三版:第四章——频率域滤波(学前了解知识)——主要内容和重点
  • 【运维基础】Linux 系统启动原理
  • 增量:增量处理
  • 游戏行业DDoS攻防实战指南
  • ApplicationContext的实现类有哪些?
  • 「PromptPilot 大模型智能提示词平台」—— PromptPilot × 豆包大模型 1.6:客户投诉邮件高效回复智能提示词解决方案
  • 芯祥科技:工业/车规级BMS芯片厂商 规格选型对比
  • Python import 详解
  • linux_https,udp,tcp协议(更新中)
  • C++ ---》string类的模拟实现
  • CRT调试堆检测:从原理到实战的资源泄漏排查指南
  • HBM Basic(VCU128)
  • nflsoi 7.29 题解
  • Python-深度学习--2信息熵,条件熵(ID3决策树),KL散度
  • 飞算JavaAI—AI编程助手 | 引领开发新时代,智能化编程的完美助手
  • python学智能算法(三十三)|SVM-构建软边界拉格朗日方程
  • 分布式微服务--Nacos持久化
  • Modstart 请求出现 Access to XMLHttpRequest at ‘xx‘
  • 用 Python 构建高质量的中文 Wikipedia 语料库:从原始 XML 到干净段落
  • rabbitMq内容整理
  • PromptPilot搭配Doubao-seed-1.6:定制你需要的AI提示prompt
  • 云计算一阶段Ⅱ——11. Linux 防火墙管理
  • LeetCood算法题~水果成篮
  • [element-plus] ClickOutside点击其他地方
  • 【IDEA】IntelliJ IDEA 中文官方文档全面介绍与总结
  • Docker 部署工程基本命令记录