Boost多线程编程

目录

thread

[thread 类总览](#thread 类总览)

构造函数

[= join joinable](#= join joinable)

[detach swap](#detach swap)

成员函数的调用

namespace::this_thread​编辑​编辑

互斥量Mutex

互斥锁mutex

递归锁recursive_mutex

定时锁

Lock

lock_guard

unique_lock

[std::lock 解决死锁问题](#std::lock 解决死锁问题)

消息队列

condition_variable

condition_variable

生产者消费者模型

atomic

atmoic

atomic_flag

[chrono 时间库](#chrono 时间库)


thread

thread 类总览

构造函数

= join joinable

C++ std::thread join()的理解 - 代萌 - 博客园

  • **谁调用了这个函数?**调用了这个函数的线程对象,一定要等这个线程对象的方法(在构造时传入的方法)执行完毕后(或者理解为这个线程的活干完了!),这个join()函数才能得到返回。

  • 在什么线程环境下调用了这个函数? 上面说了必须要等线程方法执行完毕后才能返回,那必然是阻塞调用线程的,也就是说如果一个线程对象在一个线程环境调用了这个函数,那么这个线程环境就会被阻塞,直到这个线程对象在构造时传入的方法执行完毕后,才能继续往下走,另外如果线程对象在调用join()函数之前,就已经做完了自己的事情(在构造时传入的方法执行完毕),那么这个函数不会阻塞线程环境,线程环境正常执行。


detach swap

成员函数的调用

必须传入成员函数地址和调用的对象

namespace::this_thread

互斥量Mutex

互斥锁mutex


递归锁recursive_mutex

递归锁出现的意义:假设存在这样一个场景,一个函数使用mutex 同时调用另外的一个函数里面有用到同一个mutex,则此时同一个互斥量被上了两次锁,导致死锁;而递归锁可以对互斥量拥有多层所有权,可以避免死锁;

同一个线程多次占用(递归占用次数有限,不能太多),可配合lock_guard使用,不通线程和互斥锁一致。

定时锁

Lock

lock_guard


unique_lock


std::lock 解决死锁问题

多线程共享数据的保护+互斥量概念、用法、死锁演示及解决详解(std::lock()、std::adopt_lock)_c# 两个线程共享数组保护-CSDN博客

消息队列

cpp 复制代码
#include <list>
#include <thread>
#include <mutex>
#include<iostream>

class A
{
public:
    //把收到的消息(玩家命令)入到一个队列的线程
    void inMsgRecvQueue()
    {
        for (int i = 0;i < 100;++i)
        {
            cout << "inMsgRecvQueue()执行,插入一个元素" << i << endl;
            my_mutex.lock();
            msgRecvQueue.push_back(i);
            my_mutex.unlock();
        }
    }

    bool outMsgLULProc(int& command)
    {
        // my_mutex.lock();
        std::lock_guard<std::mutex> sguard(my_mutex);
        if (!msgRecvQueue.empty())
        {
            command = msgRecvQueue.front();
            msgRecvQueue.pop_front();
            // my_mutex.unlock();
            return true;
        }
        // my_mutex.unlock();
        return false; 
    }

    //把数据从消息队列中取出的线程
    void outMsgRecvQueue()
    {
        int command = 0;
        for (int i = 0;i < 100;i++)
        {
            bool result = outMsgLULProc(command);
            if (result == true)
            {
                cout << "outMsgRecvQueue()执行,取出一个元素" << command << endl;
                //可以考虑对命令(数据)进行处理
            }
            else
            {
                cout << "outMsgRecvQueue()执行,但是目前消息队列中为空" << i << endl;
            }
        }
        cout << "end" << endl;
    }

private:
    std::list<int> msgRecvQueue;    //容器,专门用于代表玩家发送过来的命令
    std::mutex my_mutex; //创建一个互斥量 
};

int main()
{
    A myobja;
    std::thread myOutnMsgObj(&A::outMsgRecvQueue,&myobja);
    std::thread myInMsgObj(&A::inMsgRecvQueue,&myobja);
    myInMsgObj.join();
    myOutnMsgObj.join();
    return 0;
}

condition_variable


condition_variable

生产者消费者模型

cpp 复制代码
condition_variable.h头文件
    
#include <mutex>
#include <thread>
#include <chrono>
#include <deque>
#include <condition_variable>

namespace TestConditional_variable
{
	extern std::mutex g_cvMutex;
	extern std::condition_variable g_cv;
	extern std::deque<int>g_data_deque;
	extern const int MAX_NUM;
	extern int g_next_index;

	const int PRODUCER_THREAD_NUM = 3;
	const int CONSUMER_THREAD_NUM = 3;

	void producer_thread(int thread_id);
	void consumer_thread(int thread_id);

}
cpp 复制代码
condition_variable.cpp头文件
    
#include"Condition_variable.h"
#include<iostream>
namespace TestConditional_variable {

	 std::mutex g_cvMutex;
	 std::condition_variable g_cv;
	 std::deque<int>g_data_deque;
	 const int MAX_NUM = 30;

	 int g_next_index = 0;
	
	void producer_thread(int thread_id)
	{
		for (int i = 0; i < 4;i++)
		{
			std::this_thread::sleep_for(std::chrono::milliseconds(500));
			std::unique_lock<std::mutex>lk(g_cvMutex);
			g_cv.wait(lk, [](){return g_data_deque.size() <= MAX_NUM; });
            //wait的第二个参数为可执行的OBJ 反复执行直到返回true
			g_next_index++;
			g_data_deque.push_back(g_next_index);
			std::cout << "producer_thread" << thread_id << " producer data" << g_next_index;
			std::cout << " queue size:" << g_data_deque.size() << std::endl;
			g_cv.notify_all();
		}
	}

	void consumer_thread(int thread_id)
	{
		for (int i = 0; i < 4; i++)
		{
			std::this_thread::sleep_for(std::chrono::milliseconds(500));
			std::unique_lock<std::mutex>lk(g_cvMutex);
			g_cv.wait(lk, [](){return !g_data_deque.empty(); });
			g_next_index++;
			int data = g_data_deque.front();
			g_data_deque.pop_front();
			std::cout << "consumer_thread" << thread_id << " consumer data" << g_next_index;
			std::cout << " queue size:" << g_data_deque.size() << std::endl;
			g_cv.notify_all();
		}
	}

}
cpp 复制代码
#include"Condition_variable.h"
#include<iostream>

int main(int argc, char *argv[])
{
	std::thread arrProducerThread[TestConditional_variable::PRODUCER_THREAD_NUM];
	std::thread arrConsumerThread[TestConditional_variable::CONSUMER_THREAD_NUM];

	for (int i = 0; i < TestConditional_variable::PRODUCER_THREAD_NUM; i++)
	{
		arrProducerThread[i] = std::thread(TestConditional_variable::producer_thread, i);
	}
	for (int i = 0; i < TestConditional_variable::CONSUMER_THREAD_NUM; i++)
	{
		arrConsumerThread[i] = std::thread(TestConditional_variable::consumer_thread, i);
	}
	for (int i = 0; i < TestConditional_variable::PRODUCER_THREAD_NUM; i++)
	{
		arrProducerThread[i].join();
	}
	for (int i = 0; i < TestConditional_variable::CONSUMER_THREAD_NUM; i++)
	{
		arrConsumerThread[i].join();
	}
	return 0;
}

atomic

复制代码
#include<atomic>
class atomic
class atomic_flag

atmoic

atomic_flag

chrono 时间库

相关推荐
KAI773810 分钟前
2月10日QT
c++
geovindu17 分钟前
java: framework from BLL、DAL、IDAL、MODEL、Factory using postgresql 17.0
java·开发语言·postgresql
007php0071 小时前
Docker、Ollama、Dify 及 DeepSeek 安装配置与搭建企业级本地私有化知识库实践
运维·服务器·开发语言·后端·docker·容器·云计算
众乐乐_20081 小时前
JVM栈帧中|局部变量表、操作数栈、动态链接各自的任务是什么?
java·开发语言·jvm
魏翾蒨1 小时前
VBA语言的数据可视化
开发语言·后端·golang
致奋斗的我们2 小时前
项目:利用rsync备份全网服务器数据
linux·运维·服务器·开发语言·github·rsync·openeuler
獨枭2 小时前
在 MFC 应用中集成 WebView2
c++·mfc
Bluesonli3 小时前
第 9 天:UE5 物理系统 & 碰撞检测全解析!
开发语言·学习·游戏·ue5·虚幻·unreal engine
魏翾蒨3 小时前
PHP语言的数据库交互
开发语言·后端·golang
清泓y3 小时前
UE5--浅析委托原理(Delegate)
c++·ue5·ue4