创建多个线程、数据共享问题、案例代码
1.创建个等待多个线程
// 并发与多线程2_4.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include "pch.h"
#include <iostream>
#include <vector>
#include <thread>
using namespace std;
void Myprint(int inum)
{
cout << "myprint线程开始执行了,线程编号" << inum << endl;
cout << "myprint线程结束执行了,线程编号" << inum << endl;
}
int main()
{
//一 创建线程和等待多个线程
vector<thread>mythreads;
//创建10个线程,线程入口函数统一使用 myprint
//1)多线程执行顺序是乱的
//2)这种join写法更容易写出稳定程序
//3)把thread对象放入到容器里,对管理大量线程有帮助
for (int i = 0; i < 10; i++)
{
//创建10个线程,已经开始执行
mythreads.push_back(thread(Myprint, i));
}
for (auto iter = mythreads.begin(); iter != mythreads.end(); ++iter)
{
iter->join();
}
cout << "I LOVE CHINA" << endl;
}
2.数据共享问题分析
2.1只读数据共享
只读数据共享安全稳定
// 并发与多线程2_4.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include "pch.h"
#include <iostream>
#include <vector>
#include <thread>
using namespace std;
vector<int>g_v = { 1,2,3 };
void Myprint(int inum)
{
cout << "myprint线程开始执行了,线程编号" << inum << endl;
cout << "myprint线程结束执行了,线程编号" << inum << endl;
cout << "id 为" << std::this_thread::get_id() << "打印g_v值" << g_v[0] << g_v[1] << g_v[2] << endl;
}
int main()
{
//一 创建线程和等待多个线程
vector<thread>mythreads;
//创建10个线程,线程入口函数统一使用 myprint
//1)多线程执行顺序是乱的
//2)这种join写法更容易写出稳定程序
//3)把thread对象放入到容器里,对管理大量线程有帮助
for (int i = 0; i < 10; i++)
{
//创建10个线程,已经开始执行
mythreads.push_back(thread(Myprint, i));
}
for (auto iter = mythreads.begin(); iter != mythreads.end(); ++iter)
{
iter->join();
}
cout << "I LOVE CHINA" << endl;
//二 数据共享
//2.1只读数据
}
2.2 有读有写的数据
最简单的不崩溃处理 读和写不能同时进行
3.共享数据的保护案例代码
如果写和读同时进行,则会报错
这里就需要一个保护共享数据的互斥量的概念
// 并发与多线程2_4.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include "pch.h"
#include <iostream>
#include <vector>
#include <thread>
#include <list>
using namespace std;
//vector<int>g_v = { 1,2,3 };
//
//void Myprint(int inum)
//{
// cout << "myprint线程开始执行了,线程编号" << inum << endl;
// cout << "myprint线程结束执行了,线程编号" << inum << endl;
// cout << "id 为" << std::this_thread::get_id() << "打印g_v值" << g_v[0] << g_v[1] << g_v[2] << endl;
//
//}
class A
{
public:
//把玩家命令放入到一个队列的进程
void inMsgRecvQueue()
{
for (int i = 0; i < 100; i++)
{
cout << "inMsgRecvQueue执行,插入一个元素" << i << endl;
msgRecvQueue.push_back(i); //假设数字i为命令 放入队列
}
}
//读取命令的线程
void outMsgRecvQueue()
{
for (int i = 0; i < 100; i++)
{
if (!msgRecvQueue.empty())
{
int command = msgRecvQueue.front(); //返回第一个元素但不检查元素是否存在
msgRecvQueue.pop_front(); //移除第一个元素但不返回
//处理数据。。。。。
}
else
{
cout << "outMsgRecvQueue()执行,但目前消息队列为空" <<i<< endl;
}
}
cout << "end" << endl;
}
private:
std::list<int>msgRecvQueue;
};
int main()
{
// //一 创建线程和等待多个线程
//vector<thread>mythreads;
创建10个线程,线程入口函数统一使用 myprint
1)多线程执行顺序是乱的
2)这种join写法更容易写出稳定程序
3)把thread对象放入到容器里,对管理大量线程有帮助
//for (int i = 0; i < 10; i++)
//{
// //创建10个线程,已经开始执行
// mythreads.push_back(thread(Myprint, i));
//
//}
//for (auto iter = mythreads.begin(); iter != mythreads.end(); ++iter)
//{
// iter->join();
//}
//cout << "I LOVE CHINA" << endl;
//二 数据共享
//2.1只读数据
//2.2 有读有写
//最简单的不崩溃处理 读和写不能同时进行
//2.3其他案例
//数据共享:
//三 共享数据的保护案例代码
//网络游戏服务器,有两个自己创建的线程,一个线程手机玩家命令(数字表示),并把名利数据写入到一个队列中。
//另一个线程从队列中取出玩家发送来的命令,解析,然后执行玩家的动作。
//使用list,频繁的按顺序插入和删除时效率较高
//用成员函数作为线程函数的方法写线程
A myobja;
thread myOutnMsg(&A::outMsgRecvQueue, &myobja);
thread myInMsgObj(&A::inMsgRecvQueue, &myobja);
myOutnMsg.join();
myInMsgObj.join();
}