当前位置:网站首页>17.4创建多个线程、数据共享问题分析与案例代码
17.4创建多个线程、数据共享问题分析与案例代码
2022-06-11 10:59:00 【zzyzxb】
一、创建和等待多个线程
//线程入口函数
void myprint(int inum)
{
cout << "myprint线程开始执行了,线程编号id=" << inum << endl;
printf("myprint线程开始执行了,线程编号id=%d \n", inum);
//...干各种事情
cout << "myprint线程结束执行了,线程编号id=" << inum << endl;
printf("myprint线程结束执行了,线程编号id=%d \n", inum);
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(); //等待10个线程都返回
}
cout << "main主函数执行结束" << endl; //最后执行这句,整个进程退出
return 0;
}
创建10个线程,线程入口函数统一使用myprint
<1>多个线程执行顺序是乱的,跟操作系统内部对线程的运行调度机制有关;
<2>主线程等待所有的子线程运行结束,最后主线程结束;老师推荐 join 的写法,更容易写成稳定的程序;
<3>我们把 thread 对象放入到容器里管理,看起来像个 thread 数组,这对我们一次创建大量的线程并对大量线程管理很方便。
二、数据共享问题分析
vector<int> g_v = { 1,2,3 }; //共享数据,只读
//线程入口函数
void myprint(int inum)
{
cout << "id = " << this_thread::get_id() << "gv的值 = " << 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(); //等待10个线程都返回
}
cout << "main主函数执行结束" << endl; //最后执行这句,整个进程退出
return 0;
}
<1>只读数据:是安全稳定的,不需要什么特别的处理,直接读就可以;
<2>有读有写:2个线程写,8个线程读,如果代码没有特别的处理,那程序肯定崩溃;
最简单的不崩溃处理,读的时候不能写,写的时候不能读。2个线程不能同时写,8个线程不能同时读;
写的动作分10小步;由于任务切换,导致各种诡异事情发生(最可能的诡异事情还是崩溃);
<3>其他案例
数据共享 订票问题
三:共享数据的保护实战范例
网络游戏服务器,两个自己创建的线程,一个线程收集玩家命令(用一个数字代表玩家发来的命令),并把命令数据写到一个队列中。
另外一个线程从队列中取出玩家发送来的命令,解析,然后执行玩家需要的动作;
vector 和 list
list:频繁的按顺序插入和删除数据时效率高。
vector:容器随机的插入和删除数据效率高。
准备用成员函数作为线程函数的方法来写线程
class MA
{
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 command = msgRecvQueue.front(); //返回第一个元素,但不检查元素是否存在;
msgRecvQueue.pop_front(); //移除第一个元素,但不返回
//这里就考虑处理数据...
//...
}
else
{
//消息队列为空
cout << "outMsgRecvQueue()执行,但目前消息队列中为空 " << i << endl;
}
}
cout << "end" << endl;
}
private:
list<int> msgRecvQueue; //容器(消息队列),专门用于代表玩家发送的命令
};
int main()
{
MA myobj;
std::thread myOutMsgObj(&MA::outMsgRecvQueue, &myobj); //第二个参数是引用,才能保证线程里用的是同一个对象
std::thread myInMsgObj(&MA::inMsgRecvQueue, &myobj);
myOutMsgObj.join();
myInMsgObj.join();
cout << "main主函数执行结束" << endl; //最后执行这句,整个进程退出
return 0;
}
代码化解决问题:引入一个 c++ 解决多线程保护共享数据问题的第一个概念"互斥量",往脑袋里记这个词。
边栏推荐
- Using ribbon to realize client load balancing
- Jerry's acquisition of ble to check the causes of abnormal conditions such as abnormal code reset [chapter]
- 不做伪工作者
- Leetcode (Sword finger offer) - 10- ii Frog jumping on steps
- 数据库系统概论 ---- 第二章 -- 关系数据库(2.4 关系代数)
- Common construction and capacity operation of string class
- 想做钢铁侠?听说很多大佬都是用它入门的
- MWC 2022 lights up the future, and everything serves
- Remote monitoring project offline log specification
- VOC格式数据集转yolo格式数据集的方法
猜你喜欢

命令模式--进攻,秘密武器

Implementation of competition scoring system based on C language

Interpreting USB3.0 test items

Store management skills: how to manage chain stores efficiently?

设置默认收货地址【项目 商城】

985高校博士因文言文致谢走红!导师评价其不仅SCI写得好...
![Electron desktop development (development of an alarm clock [End])](/img/2b/dd59ebc8d11bedfc53020d69f1aa69.png)
Electron desktop development (development of an alarm clock [End])

Use yolov5 to train your own data set and get started quickly

小 P 周刊 Vol.08

封装组件系列-(一)-插槽及动态组件
随机推荐
Introduction to database system - Chapter 2 - relational database (2.1~2.3) (important knowledge points)
命令模式--进攻,秘密武器
985 University doctors became popular because of their thanks in classical Chinese! The tutor commented that he not only wrote well in sci
Store management skills: how to manage chain stores efficiently?
Online files are not transferred to Base64
杰理之BLEPR0 和 PR1 当普通 IO 口使用【篇】
封装组件系列-(一)-插槽及动态组件
How programmers do sidelines
Tu ne peux pas être libre sans richesse?
数字藏品系统app源码
Jerry's ble spp open pin_ Code function [chapter]
使用pydub修改wav文件的比特率,报错:C:\ProgramData\Anaconda3\lib\site-packages\pydub\utils.py:170: RuntimeWarning:
Leetcode (Sword finger offer) - 10- ii Frog jumping on steps
string类的常见构造及容量操作
施一公:我直到博士毕业,对研究也没兴趣!对未来很迷茫,也不知道将来要干什么......
迭代器模式--沙场秋点兵
收货地址列表展示【项目 商城】
Inventory of the 9 most famous work task management software at home and abroad
Writing the program into the microcontroller can control the forward and reverse rotation of the motor more conveniently and quickly
Surrounddepth: self supervised multi camera look around depth estimation