1、创建和等待多个线程
2、数据共享问题分析
3、共享数据的保护案列代码
#include<map>
#include<string>
#include<thread>
#include<list>
#include<mutex>
using namespace std;
//线程入口函数
void myprint(int inum){
cout<<"myprint线程开始执行,index="<<inum<<endl;
//干各种需要的事情
cout<<"myprint线程结束执行,index="<<inum<<endl;
}
int main(){
//一:创建和等待多个线程
vector<thread> mythreads;
//创建10个线程,线程入口函数统一使用myprint。
for(int i=0;i<10;i++){
mythreads.push_back(thread(myprint,i));/*创建 10个线程,同时
这10个线程已经并开始执行线程*/
}
for(auto iter = mythreads.begin();iter!=mythreads.end();++iter){
iter->join();
}
cout<<"i love china"<<endl;//最后执行这句,整个进程退出.
return 0;
a//多个线程的执行顺序是乱的,跟操作系统内部对线程的运行调度机制有关。
b//主线程等待所有子线程运行结束,最后主线程结束,推荐这种join的写法,更容易写出稳定的程序
c//把thread对象放入容器管理,看起来像个thread数组,这对我们一次创建大量的线程进行管理很方便
#include<map>
#include<string>
#include<thread>
#include<list>
#include<vector>
using namespace std;
vector<int> g_v = {1,2,3};//共享数据,只读
//线程入口函数
void myprint(int inum){
cout<<"id="<<std::this_thread::get_id()<<"的线程的打印g_v的值"<<g_v[0]<< g_v[1] <<g_v[2]<<endl;
return;
}
int main(){
//一:创建和等待多个线程
vector<thread> mythreads;
//创建10个线程,线程入口函数统一使用myprint。
for(int i=0;i<10;i++){
mythreads.push_back(thread(myprint,i));/*创建 10个线程,同时
这10个线程已经并开始执行线程*/
}
for(auto iter = mythreads.begin();iter!=mythreads.end();++iter){
iter->join();
}
cout<<"i love china"<<endl;//最后执行这句,整个进程退出.
return 0;
}
//数据共享问题分析
a//只读的数据,是安全稳定的,不需要特别什么处理手段,直接读可以。
b//有读有写:2个线程写,8个线程读,如果代码没有特别的处理,程序肯定奔溃,最简单的不奔溃处理,读的时候不能写,写的时候不能读。2个线程不能同时写,8个线程不能同时读;
//写的动作分10小步;由于任务切换,导致各种诡异发生(最可能的诡异事情还是奔溃);
//其他案例
//数据共享
//北京-深圳 火车站,10个售票窗口 卖票, 1,2窗口 同时都要订 99座
//共享数据的保护案列代码
//网络游戏服务器.两个自己创建的线程,一个线程收集玩家命令(用一个数据代表玩家发来的命令),并把命令数据写到一个队列中。另外一个线程用来从队列从取出玩家发送的命令,解析,然后执行玩家需要的动作;
//vector:频繁地按顺序插入和删除数据时效率高。
//list:对随机的插入和删除数据效率高
#include<map>
#include<string>
#include<thread>
#include<vector>
#include<list>
using namespace std;
class A{
public:
//把收到的消息(玩家命令)入到一个队列的线程
void inMsgRecvQueue(){
for(int i=0;i<100000; ++i){
cout<<"inMsgRecvQueue()执行,插入一个元素"<<i<<endl;
msgRecvQueue.push_back(i);/*假设这个数字i就是我们收到的命令
我直接弄到消息队列里边来*/
}
}
//把数据从消息队列中取出的线程
void outMsgRecvQueue(){
for(int i=0;i<100000;i++){
if(!msgRecvQueue.empty()){
//消息队列不为空
int commmand = msgRecvQueue.front();/*返回第一个元素
,但不检查元素是否存在*/
msgRecvQueue.pop_front();//移除第一个元素,但不返回;
//这里就考虑处理数据...
/...
}else{
cout<<"outMsgRecvQueue()执行,但目前消息队列中为空"<<i<<endl;
}
}
cout<<"end"<<endl;
}
private:
std::list<int> msgRecvQueue: //容器,专门用于代表玩家给咱们发送过来的命令
};
int main(){
A myobja;
std::thread myOutMsgObj(&A::outMsgRecvQueue,&myobja);/*第二个参数
是引用,才能保证线程里用的是用一个对象*/
std:;thread myInMsgObj(&A::inMsgRecvQueue,&myobja);
myOutMsgObj.join();
myInMsgObj.join();
return 0;
}
//准备用成员函数作为线程函数的方法来写线程。
//代码化解决问题,引入一个c++多线程保护共享数据问题概念“互斥量”,往脑袋里记这个词,下一章再讲
本文暂时没有评论,来添加一个吧(●'◡'●)