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 时间库

相关推荐
在繁华处3 小时前
Java从零到熟练(四):面向对象基础
java·开发语言
Unbelievabletobe3 小时前
解决了股票api接口盘后数据更新慢的问题
大数据·开发语言·python
cany10003 小时前
C++ -- 可变参数模板
c++
不会C语言的男孩4 小时前
C++ Primer 第2章:变量和基本类型
开发语言·c++
在繁华处4 小时前
Java从零到熟练(三):流程控制
java·开发语言·python
云泽8085 小时前
C++ 可调用对象通关指南:深度解析 Lambda 表达式、function 包装器与 bind 绑定器
开发语言·c++·算法
Tri_Function6 小时前
简单图论大学习
c++
lqqjuly6 小时前
C++ 完整知识体系—从基础语法到现代 C++23 的系统性总结
c++·c++23
王老师青少年编程7 小时前
信奥赛C++提高组csp-s之FHQ Treap
c++·csp·平衡树·信奥赛·csp-s·提高组·fhq treap
星恒随风7 小时前
Python 基础语法详解(一):从表达式、变量到数据类型
开发语言·笔记·python·学习