创建多个线程及数据共享问题分析
创建多个线程及数据共享问题分析
1.创建和等待多个线程
void myprint(int num)
{
std::cout << "myprint线程开始执行,线程编号 = " << num << std::endl;
//其他操作···
std::cout << "myprint线程结束执行,线程编号 = " << num << std::endl;
}
int main()
{
std::vector<std::thread>mythreads;
//创建10个线程,线程入口函数都是用myprint
for (int i = 0; i < 10; i++)
{
mythreads.push_back(std::thread(myprint, i));// 创建并执行线程
}
for (auto it = mythreads.begin(); it != mythreads.end(); it++)
{
it->join();//等待10个线程都返回
}
std::cout << "主线程执行完毕." << std::endl;
getchar();
return 0;
}
执行结果:
结果分析总结:
① 多个线程执行顺序通常是乱的,这跟操作系统内部线程的运行调度机制有关;
② 推荐使用join()这样让主线程等待所有子线程运行结束,最后主线程结束,这样程序更稳定。
2.数据共享问题分析
(1)只读的数据
std::vector<int>vec = { 1,2,3 };//共享数据
void myprint(int num)
{
std::cout << "ID为" << std::this_thread::get_id() << "的线程打印出的vec的值为:" << vec[0] << vec[1] << vec[2] << std::endl;
}
int main()
{
std::vector<std::thread>mythreads;
//创建10个线程,线程入口函数都是用myprint
for (int i = 0; i < 10; i++)
{
mythreads.push_back(std::thread(myprint, i));// 创建并执行线程
}
for (auto it = mythreads.begin(); it != mythreads.end(); it++)
{
it->join();//等待10个线程都返回
}
std::cout << "主线程执行完毕." << std::endl;
getchar();
return 0;
}
执行结果:
结果分析总结:
① 只读数据是安全稳定的,不需要特别的处理手段。
(2)有读有写
如,2个线程写,8个线程读,若果代码特别处理,程序必然崩溃。
最简单的处理手段:读的时候不能写,写的时候不能读。即,2个线程不能同时写,8个线程不能同时读。
3.共享数据的保护案例
网络游戏服务器,创建两个线程,其中一个线程收集玩家命令(用一个数字代表玩家发送的命令),并把命令写到队列中;另外一个线程,从队列中取出玩家发送来的命令并解析,然后执行玩家需要的动作。
#include<iostream>
#include<vector>
#include<list>
#include<thread>
class A
{
public:
//把收到的消息(玩家命令)写入到一个队列的线程
void inMsgRecvQueue()
{
for (int i = 0; i < 100000; ++i)
{
std::cout << "inMsgRecvQueue()执行,插入一个元素" << i << std::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();//移除list首元素
}
else
{
std::cout << "outMsgRecvQueue()执行,但目前消息队列中为空" << std::endl;
}
}
std::cout << "END" << std::endl;
}
private:
std::list<int>msgRecvQueue;//存储玩家发送过来的命令--消息队列
};
int main()
{
A myobj;
std::thread m_outMsgThread(&A::outMsgRecvQueue, &myobj);
std::thread m_inMsgThread(&A::inMsgRecvQueue, &myobj);
m_outMsgThread.join();
m_inMsgThread.join();
getchar();
return 0;
}
因为没有控制读写,所以执行出现问题:
解决方法在下一节解决多线程保护共享数问题---互斥量
。