一、创建和等待多个线程
void TextThread()
{
cout << "我是线程" << this_thread::get_id() << endl;
/* … */
cout << "线程" << this_thread::get_id() << "执行结束" << endl;
}
//main函数里 vector threadagg;
for (int i = 0; i < 10; ++i)
{
threadagg.push_back(thread(TextThread));
}
for (int i = 0; i < 10; ++i)
{
threadagg[i].join();
}
- 把thread对象放入到容器中管理,看起来像个thread对象数组,对一次创建大量的线程并对大量线程进行管理有好处
- 多个线程执行顺序是乱的,跟操作系统内部对线程的运行调度机制有关
二、数据共享问题分析
2.1 只读的数据
是安全稳定的
2.2 有读有写
- 若不加处理,就会出错
- 最简单的防止崩溃方法:读的时候不能写,写的时候不能读。
- 写的动作分10小步,由于任务切换,导致各种诡异的事情发生(最可能的还是崩溃)
#include <iostream>
#include <thread>
#include "vector"
using namespace std;
vector<int> g_v = {1,2,3};//共享数据的
vector<thread>mythreads;
void myPrint(int num)
{
cout<<"id是:"<<this_thread::get_id() << "的线程打印数值"<<g_v[0]<<" "<<g_v[1]<<"\n";
return ;
}
int main()
{
for(int i =0;i<10;i++){
mythreads.push_back(thread(myPrint,i));//创建10线程,并且线程开始执行了
}
for(auto iter = mythreads.begin();iter != mythreads.end();iter++){
iter -> join();
}
//myThread.detach();
cout << "Hello World!" << endl;
}
三、共享数据的保护案例代码
案例模拟的:网络游戏服务器: 两个自己创建的线程,一个线程收集玩家的命令,并把命令数据写到一个数据队列之中,另一个线程从队列读取数据,进行解析,并且执行玩家的命令。
c++ 解决多线程保护数据的第一个概念,互斥量的概念。
// 会运行乱套的
#include <iostream>
#include <thread>
#include "vector"
#include "list"
using namespace std;
vector<int> g_v = {1,2,3};//共享数据的
vector<thread>mythreads;
void myPrint(int num)
{
cout<<"id是:"<<this_thread::get_id() << "的线程打印数值"<<g_v[0]<<" "<<g_v[1]<<"\n";
return ;
}
class A{
public:
//收到的玩家命令入到一个队列之中。
void inreceivedQueue(){
for(int i=0 ;i<10000; i++){
cout<<"receivedQueue开始执行的,插入一个元素"<<i<<endl;
msgrecvQueue.push_back(i);
}
}
void outrecieveQueue(){
for(int i=0;i<10000;i++){
if(!msgrecvQueue.empty()){
//消息不为空
int command = msgrecvQueue.front();//返回第一个元素的
msgrecvQueue.pop_front();//除掉
} else{
//空
cout<<"outreciveQueue小子队列是空的"<< i<<"\n";
}
}
}
private:
list<int>msgrecvQueue;//容器 代表玩家发送过来的命令;
};
int main()
{
A myobja;
std::thread myout(&A::outrecieveQueue,&myobja);
std::thread myin(&A::inreceivedQueue,&myobja);
myin.join();
myout.join();
return 0;
}