目录
[thread 类总览](#thread 类总览)
[= join joinable](#= join joinable)
[detach swap](#detach swap)
[std::lock 解决死锁问题](#std::lock 解决死锁问题)
[chrono 时间库](#chrono 时间库)
thread
thread 类总览
![](https://i-blog.csdnimg.cn/direct/e889a981686d4168b5d14bec20023c55.png)
![](https://i-blog.csdnimg.cn/direct/713b82d3c1d04d99b49004a66a3217fc.png)
构造函数
![](https://i-blog.csdnimg.cn/direct/e8e6da495328483b8795f7d5e065b1ea.png)
![](https://i-blog.csdnimg.cn/direct/930d9d2496454fe7a5dad62d0c081d92.png)
= join joinable
C++ std::thread join()的理解 - 代萌 - 博客园
-
**谁调用了这个函数?**调用了这个函数的线程对象,一定要等这个线程对象的方法(在构造时传入的方法)执行完毕后(或者理解为这个线程的活干完了!),这个join()函数才能得到返回。
-
在什么线程环境下调用了这个函数? 上面说了必须要等线程方法执行完毕后才能返回,那必然是阻塞调用线程的,也就是说如果一个线程对象在一个线程环境调用了这个函数,那么这个线程环境就会被阻塞,直到这个线程对象在构造时传入的方法执行完毕后,才能继续往下走,另外如果线程对象在调用join()函数之前,就已经做完了自己的事情(在构造时传入的方法执行完毕),那么这个函数不会阻塞线程环境,线程环境正常执行。
-
detach swap
![](https://i-blog.csdnimg.cn/direct/acaab1e0579a4ecabe61dd72af91b0ec.png)
成员函数的调用
必须传入成员函数地址和调用的对象
![](https://i-blog.csdnimg.cn/direct/f5fd58b32b424f3cbedd69f53da7e1f4.png)
namespace::this_thread![](https://i-blog.csdnimg.cn/direct/c0598e76b52047de8dddac160721bb61.png)
![](https://i-blog.csdnimg.cn/direct/b576da06c4394ddd99b34a7abf4f593c.png)
互斥量Mutex
![](https://i-blog.csdnimg.cn/direct/e8d380d9b4cb4e359e1157c2ef3c93f6.png)
互斥锁mutex
递归锁recursive_mutex
![](https://i-blog.csdnimg.cn/direct/4b00e70cb17f4c71b32e95e61ca34dc2.png)
递归锁出现的意义:假设存在这样一个场景,一个函数使用mutex 同时调用另外的一个函数里面有用到同一个mutex,则此时同一个互斥量被上了两次锁,导致死锁;而递归锁可以对互斥量拥有多层所有权,可以避免死锁;
同一个线程多次占用(递归占用次数有限,不能太多),可配合lock_guard使用,不通线程和互斥锁一致。
![](https://i-blog.csdnimg.cn/direct/0a616241ae974ae3afb811dd6ef59daa.png)
定时锁
![](https://i-blog.csdnimg.cn/direct/962e33c191e24ba68b9692155ed6cfde.png)
![](https://i-blog.csdnimg.cn/direct/8c808deffba24a4d9626127a39938aaa.png)
Lock
lock_guard
unique_lock
![](https://i-blog.csdnimg.cn/direct/7cb15e015a3b44428a22365c85a27aec.png)
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
![](https://i-blog.csdnimg.cn/direct/3783f9cb95e74af0ae4bc6b4a9b7b8cb.png)
生产者消费者模型
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