博客
关于我
(C++11/14/17学习笔记):创建多个线程、数据共享问题分析及案例
阅读量:340 次
发布时间:2019-03-04

本文共 2963 字,大约阅读时间需要 9 分钟。

创建多个线程、数据共享问题分析、案例代码

创建和等待多个线程

创建多个线程是一个常见的操作,但如果不正确管理,可能会导致逻辑错误或性能问题。在C++中,可以通过std::thread来创建线程,并使用join方法等待所有线程结束。

【引例】

#include 
#include
#include
using namespace std;void myprint(int val) { cout << "myprint线程开始执行了,编号为: " << val << endl; // ... cout << "myprint线程执行完毕了,编号为: " << val << endl; return; }int main() { vector
my_threads; for (int i = 0; i < 10; ++i) { my_threads.push_back(thread(myprint, i)); } for (auto iter = my_threads.begin(); iter != my_threads.end(); ++iter) { iter->join(); } cout << "主线程结束" << endl; return 0; }

要点:

  • 多个线程执行顺序是随机的,与操作系统的线程调度机制有关。
  • 使用join方法等待所有子线程结束,避免主线程等待时间过长。
  • 将线程对象存储在容器中,方便管理和操作。

数据共享问题分析

在多线程环境中,数据共享可能导致竞态条件或其他并发问题。以下是常见情况的分析:

只读的数据

只读数据是安全的,因为所有线程都只能读取,不会修改数据。直接使用即可。

【示例】

#include 
#include
#include
using namespace std;vector
vec{1, 2, 3}; void myprint(int val) { cout << "线程id为:" << this_thread::get_id() << "\tvec的值\t" << vec[0] << "\t" << vec[1] << "\t" << vec[2] << endl; }int main() { vector
my_threads; for (int i = 0; i < 10; ++i) { my_threads.push_back(thread(myprint, i)); } for (auto iter = my_threads.begin(); iter != my_threads.end(); ++iter) { iter->join(); } cout << "主线程结束" << endl; return 0; }

要点:

  • 只读数据不需要额外处理,直接访问即可。

有读有写

当有线程同时进行读和写操作时,必须采取措施防止竞态条件。最简单的方法是确保读操作和写操作互斥。

【示例】

假设有2个写线程和8个读线程,直接操作共享数据会导致崩溃。正确的做法是:

  • 读操作和写操作不能同时进行。
  • 确保在写操作时,其他线程无法读取数据。
  • // 示例不提供完整代码,但核心思想是:  // - 在写操作时,阻止其他线程读取  // - 在读操作时,确保数据已写好

    要点:

    • 读和写操作必须互斥,否则程序会崩溃。
    • 使用互斥量(如mutex)是解决这种情况的常用方法。

    共享数据的保护案例代码

    场景: 网络游戏服务器,两个线程分别处理玩家命令。

    #include 
    #include
    #include
    #include
    using namespace std;class A { public: void inMsgRecvQueue() { for (int i = 1; i < 10000; ++i) { cout << "inMsgRecvQueue执行了,插入一个元素 " << i << endl; msgRecvQueue.push_back(i); } } void outMsgRecvQueue() { for (int i = 1; i < 10000; ++i) { if (!msgRecvQueue.empty()) { int command = msgRecvQueue.front(); msgRecvQueue.pop_front(); // 根据command执行具体操作 } else { cout << "outMsgRecvQueue执行了,但是当前消息队列为空 " << i << endl; } } cout << "outMsgRecvQueue()执行完毕" << endl; } private: list
    msgRecvQueue; }; int main() { A obja; thread outMsgThread(&A::outMsgRecvQueue, &obja); thread inMsgThread(&A::inMsgRecvQueue, &obja); inMsgThread.join(); outMsgThread.join(); cout << "主线程结束" << endl; return 0; }

    问题:

    • 两个线程同时操作消息队列,会导致数据竞争。
    • 如果没有互斥措施,程序可能崩溃。

    解决方法:

    • 使用互斥量包围关键操作,确保只允许一个线程执行读或写操作。
    • 例如,给读操作加上互斥锁,防止同时写入和读取。

    通过以上内容,可以看出多线程开发中数据共享问题的关键在于正确管理共享资源,避免竞态条件,并在需要时使用互斥机制确保线程安全。

    转载地址:http://mbyr.baihongyu.com/

    你可能感兴趣的文章
    Python-Url编码和解码
    查看>>
    (十)Flutter 路由 push pop 与List 中溅墨(我咋觉得应该叫水波纹)效果(InkWell)
    查看>>
    jQuery tabs侧面显示 纵向显示
    查看>>
    windows环境下生成ssh keys
    查看>>
    2019年一个程序员的回顾与成长计划
    查看>>
    CSDN博客自定义栏目——Google、百度、必应站内搜索框
    查看>>
    vue 双项绑定的实例 货币转换
    查看>>
    vue if else用法。
    查看>>
    a标签提交表单
    查看>>
    vue 官方实例教程 markdown demo
    查看>>
    CSS border-style 属性
    查看>>
    Python数据类型 列表、元组、集合、字典的区别和相互转换
    查看>>
    宝塔配置404 502页面
    查看>>
    jquery each 操作批量数据
    查看>>
    Mac OS X 下 su 命令提示 sorry 的解决方法
    查看>>
    vue-router 缓存路由组件对象
    查看>>
    移动端 触摸事件和mousedown、mouseup、click事件之间的关系
    查看>>
    js中事件捕获和事件冒泡(事件流)
    查看>>
    js的各种数据类型判断(in、hasOwnProperty)
    查看>>
    严格模式、混杂模式与怪异模式
    查看>>