一、创建多个子线程

前面三章讲的例子都是只有一个子线程和主线程,然而实际中有多个子线程。那么下面介绍如何创建多个子线程。

 #include <iostream>
#include <vector>
#include <list>
#include <thread>
using namespace std; void mythread(int i)
{
cout << "id为" << std::this_thread::get_id() << "的线程" << endl;
cout << "i=" << i << endl;
return;
} int main()
{
vector<thread> mythreads;
for (int i = ; i < ; i++)
{
mythreads.push_back(thread(mythread, i)); //创建是10个线程并放入容器中
}
for (auto ite = mythreads.begin(); ite != mythreads.end(); ++ite)
{
ite->join(); //主线程等待10个线程执行完
}
cout << "主线程执行完毕" << endl;
system("pause");
return ;
}

运行结果

可以看出,虽然所有子线程执行完了才到主线程,但各个子线程的执行期间是乱的,没有谁等谁。那么就会引发一个数据共享的问题。

二、数据共享问题

如果多个线程之间知识单纯的读取数据,那么程序是不会出现奔溃等严重问题的,是安全稳定的。但如果既读数据又写数据,程序很有可能崩溃。比如有5个线程,2个线程写数据,3个线程读取同样的数据,试想如果写数据的线程还没写入数据,其他线程就进行读数据操作了,那么必然会出现问题。下面举一个例子说明。

 #include <iostream>
#include <vector>
#include <list>
#include <thread>
using namespace std;
//队列,先进先出
class A
{
private:
list<int> msg;
public:
//把数据写入队列
void inMsgRecv()
{
for (int i = ; i < ; i++)
{
cout << "插入一个元素" << i << endl;
msg.push_back(i);
}
}
//从队列读数据
void outMsgRecv()
{
for (int i = ; i < ; i++)
{
if (!msg.empty())
{
int GetMsg = msg.front(); //接受消息队列的首部
msg.pop_front(); //移除首部
//....然后可以对GetMsg进行你想要的操作
//cout << "GetMsg:" << GetMsg << endl;
}
else
{
cout << "没有数据可读" << endl;
}
}
}
}; int main()
{
A myobj;
//以成员函数作为线程函数,第一个&是取地址,第二个&是引用
thread mythread1(&A::inMsgRecv, &myobj);
thread mythread2(&A::outMsgRecv, &myobj);
mythread1.join();
mythread2.join();
system("pause");
return ;
}

运行结果

那么要处理多线程的数据共享问题,就要涉及一个概念“互斥量”,下面一章将会讲到。

C++多线程基础学习笔记(四)的更多相关文章

  1. Java基础学习笔记四 Java基础语法

    数组 数组的需求 现在需要统计某公司员工的工资情况,例如计算平均工资.最高工资等.假设该公司有50名员工,用前面所学的知识完成,那么程序首先需要声明50个变量来分别记住每位员工的工资,这样做会显得很麻 ...

  2. Java基础学习笔记(四) - 认识final关键字、权限修饰符和内部类

    一.final关键字 为什么要使用 final 关键字? 通过继承我们知道,子类可以重写父类的成员变量和方法.final 关键字可以用于修饰父类,父类成员变量和方法,使其内容不可以被更改. 1.被修饰 ...

  3. C++多线程基础学习笔记(一)

    下面分三个方面多线程技术的必须掌握一些基本知识. 1.进程 2.线程 3.并发 (1)进程 一个可执行程序运行起来了,即为创建了一个进程.如在电脑上打开了word,就创建了一个word进程,打开QQ, ...

  4. loadrunner基础学习笔记四

    在loadrunner中,通过将一系列操作标记为事务,可以将它们指定为要评测的操作. loadrunner收集关于事务执行时间长度的信息,并将结果显示在用不同单色标识的图和报告中. 可以这些信息了解应 ...

  5. JSP实现数据保存(web基础学习笔记四)

    session对象: //服务端设置Session属性 session.setAttribute("user", username); //客户端接收Session Object ...

  6. C++多线程基础学习笔记(十)

    一.Windows临界区的基本用法 CRITICAL_SECTION my_winsc;              //定义一个Windows的临界区,相当于一个mutex变量 InitializeC ...

  7. C++多线程基础学习笔记(九)

    一.std::atomic续谈 上一章说到std::atomic是针对一个变量的,这里补充一下针对的变量操作一般是++,+=,--,&=等等运算 .以下这种不可取:a=a+1; 二.std:: ...

  8. C++多线程基础学习笔记(八)

    shared_futrue和futrue_status的用法 shared_futrue是一个类模板,类似于futrue,不同的是它的成员函数get()可以使用多次,因为是复制数据,而futrue的g ...

  9. C++多线程基础学习笔记(七)

    一.std::async和std::future的用法 std::async是一个函数模板,std::future是一个类模板 #include <iostream> #include & ...

随机推荐

  1. 【UOJ#228】 基础数据结构练习题

    题目描述 sylvia 是一个热爱学习的女孩子,今天她想要学习数据结构技巧. 在看了一些博客学了一些姿势后,她想要找一些数据结构题来练练手.于是她的好朋友九条可怜酱给她出了一道题. 给出一个长度为 n ...

  2. bzoj4321

    queue2 HYSBZ - 4321 n 个沙茶,被编号 1~n.排完队之后,每个沙茶希望,自己的相邻的两 人只要无一个人的编号和自己的编号相差为 1(+1 或-1)就行:  现在想知道,存在多少方 ...

  3. MySQL_(Java)使用JDBC创建用户名和密码校验查询方法

    MySQL_(Java)使用JDBC向数据库发起查询请求 传送门 MySQL数据库中的数据,数据库名garysql,表名garytb,数据库中存在的用户表 通过JDBC对MySQL中的数据用户名和密码 ...

  4. $\LaTeX$数学公式大全9

    $9\ Math\ mode\ accents$ $\acute{a}$ \acute{a} $\breve{a}$ \breve{a} $\ddot{a}$ \ddot{a} $\grave{a}$ ...

  5. git上传项目已经删除文件,但是Jenkins中没有删除

    jenkins 缓存造成的,需要清理工作空间

  6. Linux上Python的安装升级

    1.下载 cd /usr/local/src/ wget https://www.python.org/ftp/python/3.5.1/Python-3.5.1.tgz 2.安装,在/usr/loc ...

  7. Node.js自学完全总结

    零.什么是Node.js? 引用Node.js官方网站的解释如下: Node.js® is a JavaScript runtime built on Chrome's V8 JavaScript e ...

  8. Android jni/ndk编程二:jni数据类型转换(primitive,String,array)

    一.数据类型映射概述 从我们开始jni编程起,就不可能避开函数的参数与返回值的问题.java语言的数据类型和c/c++有很多不同的地方,所以我们必须考虑当在java层调用c/c++函数时,怎么正确的把 ...

  9. ArrayList && HashMap扩容策略

    ArrayList扩容策略:默认10 扩容时是base + base/2, 即10 15 22 33 49...扩容时不安全:grow方法扩容时,赋值 elementData = Arrays.cop ...

  10. Cortex-M3 异常中断向量表

    [Cortex-M3异常与中断] 支持10个系统异常和最多240个外部中断: 支持3个固定的高优先级和多达256级的可编程优先级,支持128级抢占: #0~15在Cortex-M3中定义,IRQ#0~ ...