#include<iostream>
#include<thread>
#include<vector>
#include<list>
#include<mutex>
using namespace std;
//线程入口函数
void myprint(int num)
{
cout << "线程开始了:" << num << endl;
cout << "线程结束了" << num << endl;
return;
}
class A {
public:
//把收到的消息(玩家命令)入到一个队列的线程
void inMsgRecvQueue()
{
for (int i = 0; i < 100000; i++)
{
cout << "inMsgRecvQueue()执行,插入一个元素" << i << endl;
my_mutex.lock();
msgRecvQueue.push_back(i);
my_mutex.unlock();
}
}
bool outMsgLULproc(int &command)
{
lock_guard<mutex>sbguard(my_mutex);//guard就相当于是一个模板,用mutex来对guard进行实例化
//sbguard是起的对象名
//lock_guard构造函数里面执行mutex::lock()
//lock_guard析构函数执行unlock
// 在guard保护的区域内操作共享数据
//my_mutex.lock();
my_mutex.lock();//锁的顺序一样,不会死锁
my_mutex2.lock();
//my_mutex2.lock();//锁的顺序不一样,会发生死锁
//my_mutex.lock();
if (!msgRecvQueue.empty())
{
int command = msgRecvQueue.front();
msgRecvQueue.pop_front();//移除第一个元素,但是不返回
//这里就考虑处理数据
//my_mutex.unlock();
return true;
}
//my_mutex.unlock();
return false;
}
//把数据从消息队列中取出的过程
void outMsgRecvQueue()
{
int commond = 0;
if(outMsgLULproc(commond))
for (int i = 0; i < 100000; i++)
{
if (outMsgLULproc(commond))
{
cout << "成功从队列中取出元素:" << commond << endl;
}
else
{
cout << "消息队列为空" << i << endl;
}
}
cout << "end" << endl;
}
private:
std::list<int>msgRecvQueue;//容器,消息队列,专门用来代表玩家发送过来的命令。
std::mutex my_mutex;//创建一个互斥量
std::mutex my_mutex2;//创建第二个互斥量(用来演示死锁问题)
};
int main()
{
//a:多个线程的执行顺序是混乱的,跟操作系统内部对线程的运算调度机制有关
//b:主线程等待所有子线程运行结束,主线程最后结束(join)
//c:我们将thread拖拽到容器内进行管理,看起来像一个thread对象数组,这对我们一次性创建大量线程有帮助
vector<thread>mythreads;//创建多个线程
A myobja;
thread myoutn(&A::outMsgRecvQueue, &myobja);
thread myinn(&A::inMsgRecvQueue, &myobja);
myoutn.join();
myinn.join();
/*for (int i = 0; i < 10; i++)
{
mythreads.push_back(thread(myprint, i));
}
for (int i = 0; i < 10; i++)
{
mythreads[i].join();
}*/
/*for (auto iter = mythreads.begin(); iter != mythreads.end(); iter++)进程阻塞
{
iter->join();
}*/
cout << "主线程结束" << endl;
//保护共享数据,操作时,某个线程用代码把共享数据锁住,操作数据,解锁
//其他想操作共享数据的线程必须等待解锁,锁定住,操作,解锁
//互斥量
//一:互斥量的基本概念
//互斥量是个类对象。理解成一把锁,多个线程尝试用lock()成员函数来加锁这把锁头,只有一个线程能够锁定成功(成功的标志)
//如果没锁成功,那末流程卡在lock()这里不断尝试去锁这把锁头
//互斥量使用的时候要小心,保护数据不多也不少,少了,没达到保护效果,多了,影响效率
//互斥量的用法
//(2.1)lock(),unlock()
//步骤:先lock(),操作共享数据,unlock()
//lock()和unlock()要成对使用,有lock必然要有unlock,
//为了防止大家忘记unlock,引入了一个叫std::lock_guard的类模板:你忘记unlock不要紧,我替你unlock
//学习过智能指针(unique_ptr<>),你忘记释放内存不要紧,我来释放
//(2.2) std::lock_guard类模板,直接取代lock和unlock(不能再用lock和unlock)
//死锁
//有金银两个锁头,进程A先拿到金锁头,进程B先拿到银锁头,但是拿完后两个线程都想要对方的锁头,此时两个线程也并没有解锁,导致两个进程卡死,造成死锁
//死锁的解决方法
//保证两个锁的顺序相同
//1:std::lock(函数模板,用来处理多个互斥量的时候才出场)
//能力;一次锁住两个或者两个以上的互斥量(至少两个)
//如果互斥量中有一个没锁住,它就在哪里等着,等所有互斥量都锁柱,它才能能往下走
//如果只是锁了一个,另外一个没锁柱,则它立即把锁住的解锁
system("pause");
return 0;
}