一、创建、等待多线程
后创建的线程不一定比先创检的线程慢。
多个线程的执行顺序是乱的,跟操作系统内部的线程调度机制有关。
把thread放入到容器里进行管理和调度。
1 #include <iostream> 2 #include <thread> //线程 3 #include <vector> 4 using namespace std; 5 6 void myprt(int num){ 7 cout << "线程开始,线程编号:" << num << endl; 8 cout << "线程结束,线程编号:" << num << endl; 9 return; 10 } 11 int main(){ 12 //创建多个线程,线程入口函数统一使用myprt 13 vector<thread> mythreads; 14 for(int i=0;i<10;i++){ 15 mythreads.push_back(thread(myprt,i));//创建并执行线程 16 } 17 for(auto iter=mythreads.begin();iter!=mythreads.end();iter++){ 18 iter->join();//等待10个线程都返回 19 } 20 cout<<"main end"<<endl; 21 return 0; 22 }
二、数据共享
1、只读数据
1 #include <iostream> 2 #include <thread> //线程 3 #include <vector> 4 using namespace std; 5 6 vector<int> g_v={1,2,3};//共享数据是安全稳定的 7 void myprt(int num){ 8 //cout << "线程开始,线程编号:" << num << endl; 9 //cout << "线程结束,线程编号:" << num << endl; 10 cout<< "id:"<<std::this_thread::get_id()<<"的线程打印g_v的值"<<g_v[0]<<endl; 11 return; 12 } 13 int main(){ 14 //创建多个线程,线程入口函数统一使用myprt 15 vector<thread> mythreads; 16 for(int i=0;i<10;i++){ 17 mythreads.push_back(thread(myprt,i));//创建并执行线程 18 } 19 for(auto iter=mythreads.begin();iter!=mythreads.end();iter++){ 20 iter->join();//等待10个线程都返回 21 } 22 cout<<"main end"<<endl; 23 return 0; 24 }
2、有读有写
比如两个线程写,8个线程读,肯定会崩溃。
由于任务切换,会导致各种诡异的事情发生。
最简单的不崩溃方法:读的时候不写,写的时候不读,多个线程不能同时写,多个线程不能同时读;
三、共享数据的保护案例代码
c++解决多线程保护共享数据问题的概念:互斥量!
1 #include <iostream> 2 #include <thread> //线程 3 #include <vector> 4 #include <list> 5 /* 6 网络游戏服务器 7 创建两个线程,一个线程收集玩家命令(用一个数字代表玩家命令),并把命令数据写到一个队列中; 8 另一个线程从队列中取出玩家发送来的命令,解析,然后执行玩家需要的动作。 9 list:频繁顺序插入和删除数据时效率高; 10 vector:频繁随机插入和删除数据时效率高; 11 准备使用成员函数来作为线程函数 12 */ 13 using namespace std; 14 class A{ 15 public: 16 //把收到的消息(玩家命令)让入到一个队列中的线程函数 17 void InMsgQue(){ 18 for(int i=0;i<100;i++){ 19 cout<<"InMsgQue执行,插入一个元素"<<i<<endl; 20 MyQue.push_back(i);//假设i就是命令 21 } 22 23 } 24 //把数据从消息队列中取出来的线程函数 25 void OutMsgQue(){ 26 for(int i=0;i<100;i++){ 27 if(!MyQue.empty()){ 28 //消息不空 29 int command = MyQue.front();//返回第一个元素,但是不检查元素是否存在,所以要if先判断 30 MyQue.pop_front(); 31 //接下来就考虑处理数据......... 32 } 33 else{ 34 cout << "OutMsgQue执行,但是消息队列为空"<<i << endl; 35 } 36 37 } 38 cout<<"end"<<endl; 39 } 40 private: 41 list<int> MyQue; 42 }; 43 44 int main(){ 45 A myobj; 46 std::thread myout(&A::OutMsgQue,&myobj); 47 std::thread myin(&A::InMsgQue,&myobj);//必须市引用,才能保证线程用的是同一个对象 48 myout.join(); 49 myin.join(); 50 cout<<"main end"<<endl; 51 return 0; 52 }
上面代码有个问题,就是收集命令和取出命令是对共享队列同时进行的,同时对同一个数组进行修改,会导致崩溃。
下面请看互斥量!