C++ | 多线程资源抢占bug解决

news2024/11/16 5:46:32

多线程资源抢占bug解决

文章目录

  • 多线程资源抢占bug解决
    • bug说明
    • 原因排查
    • 解决
    • 经验
      • >>>>> 欢迎关注公众号【三戒纪元】 <<<<<

bug说明

最近调试程序,程序在Release版本下可运行,一直没有问题,在Debug模式下编译后,就会报错。

但是如果将 DEBUG 的编译条件 由“-Og”改成 “-O2” 或者 “-O3”,即增大系统的优化力度,该报错又没有了。

原因排查

通过一系列排查,最终发现

  • 获取id的时候const auto &id = pt2idx[global_id];,循环中多个global_id为0,从而得到的label[id]的值为0,计算randy_id的时候uint32_t randy_id = label[id] - 1;,因为是无符号的,所以 0 - 1 得到一个很大的值,造成了通过randy_id再取值的时候数组越界。

  • 追根溯源,发现pt2idx[global_id]的值是在前一函数中多个线程中赋值的。打印日志发现,因为没有加锁,导致多个线程同时写入的时候发生了资源抢占。

但是pt2idx数组,已经提前申请好了一个很大的空间,理论上来说,多个线程依次向数组中填值即可,可是Debug模式下就会有问题。

因此解决资源抢占问题即可。

解决

后台有朋友说,直接加锁不就行了吗?

是的,加锁是可以直接解决问题。但有时候加锁会造成单一线程写入的时候,其他线程都在等待的问题,所以效率和时间得需要根据具体场景制定。

现在来看看不加锁如何解决这种多线程写入问题。

资源抢占都是对公共变量或公共数组写入的时候发生的,因为归根到底还是对公共资源的竞争。

就像球场上,大家都在争夺1个球,都想控球,完成自己的任务,这就是资源抢占。有“资深球迷”就会说了,大家打球这么辛苦,这么多人玩1个球,如果每人发一个球,不就不抢了吗?这当然是个冷笑话,不过思路已经很明显了,为每个人配个球。

解决办法:

为每个线程配备一个数组,每个线程将global_id写入自己的数组,线程结束后,再对各个线程的global_id 数组进行合并

这里线程开启前,声明了1个std::vector<std::vector<int32_t>>,第1层vector是按照线程个数分配的,第2层vector是每个线程单独使用自己的数组 std::vector<int32_t>,这样就不会造成资源抢占了

// 线程开始之前
const uint32_t TotalThreadNum = 10;
std::vector<std::vector<int32_t>> threads_ids(TotalThreadNum);

// 线程内部
auto &arr_ids = threads_ids[i]; // i 为 线程序号
arr_ids.emplace_back(global_id);

最后对每个线程获取到的 global_id数组进行合并,因为是顺序访问数组,所以速度会很快

经验

  • 避免多线程资源抢占,可以加锁,加锁后各线程不抢占资源,每次允许1个线程读写数据;
#include <mutex>
 mutable std::mutex mutex_;
std::lock_guard<std::mutex> lock(mutex_);
  • 避免多线程同时访问公共变量,读取可以,如果写入,必须明确写入的位置,如果容器是动态分配的,事先也不知道要向公共容器里写入多少数据,可以为每个线程分配单独的容器,最后再合并。

  • 使用加锁或者不加锁的方法,需要权衡加锁的等待的代价和不加锁最终统一拷贝的代价,不同场景需要不同配置


>>>>> 欢迎关注公众号【三戒纪元】 <<<<<

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/700913.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Leetcode42 接雨水

给定 n 个非负整数表示每个宽度为 1 的柱子的高度图&#xff0c;计算按此排列的柱子&#xff0c;下雨之后能接多少雨水。 输入&#xff1a;height [0,1,0,2,1,0,1,3,2,1,2,1] 输出&#xff1a;6 解释&#xff1a;上面是由数组 [0,1,0,2,1,0,1,3,2,1,2,1] 表示的高度图&#xf…

【javascript】防止内容被复制

在JavaScript中&#xff0c;我们可以使用onselectstart事件来防止页面内容被选取。此时无法选取所要的内容。 代码&#xff1a; <!DOCTYPE html> <html><head><meta charset"utf-8"><script>window.onload function() {document.bod…

计算机网络————网络层

文章目录 网络层设计思路IP地址IP地址分类IP地址与硬件地址 协议ARP和RARPIP划分子网和构造超网划分子网构造超网&#xff08;无分类编址CIDR&#xff09; ICMP 虚拟专用网VPN和网络地址转换NATVPNNAT 网络层设计思路 网络层向上只提供简单灵活的、无连接的、尽最大努力交付的数…

mysql表中出现特殊符号(逗号,点号),如何进行查询或操作

mysql表中出现特殊符号&#xff08;逗号&#xff0c;点号&#xff09;&#xff0c;如何进行查询或操作 一、背景说明二、需要把表"引"起来&#xff0c;tab键上面的那个按钮&#xff0c;不是引号 一、背景说明 当mysql表名中出现如点号&#xff08;.&#xff09;&…

安装并使用docker

1、安装docker 1.1、更新现有的包列表&#xff1a; sudo apt update 1.2、用apt安装一些允许通过HTTPS才能使用的软件包&#xff1a; sudo apt install apt-transport-https ca-certificates curl software-properties-common 1.3、将官方Docker存储库的GPG密钥添加到您的系统…

二.Elasticsearch进阶

建议从这里开始看&#xff1a;Elasticsearch快速入门及使用 Elasticsearch进阶 一.Elasticsearch检索方式1.uri 检索参数(不常用)2.uri 请求体(常用&#xff0c;也叫Query DSL) 二.Query DSL语法举例1.match全文匹配2.match_phrase短语匹配3.multi_match多字段匹配4.bool复合…

在Gradio中创建交互式代码编辑器:介绍Code模块和其功能

❤️觉得内容不错的话&#xff0c;欢迎点赞收藏加关注&#x1f60a;&#x1f60a;&#x1f60a;&#xff0c;后续会继续输入更多优质内容❤️ &#x1f449;有问题欢迎大家加关注私戳或者评论&#xff08;包括但不限于NLP算法相关&#xff0c;linux学习相关&#xff0c;读研读博…

Matlab评价模型--灰色关联度分析

评价模型–灰色关联度分析 灰色关联度分析 基本思想 灰色关联分析的基本思想 是根据序列曲线几何形状的相似程度来判断其联系是否紧密&#xff0c;曲线越接近&#xff0c;相应序列之间的关联度就越大&#xff0c;反之则越小。 此方法可用于 进行系统分析&#xff0c;也可应用…

uniapp顶部导航栏被遮住显示问题

解决uniapp顶部导航栏被遮住显示问题 uniapp官方给了处理的方案&#xff0c;即css变量&#xff0c;–status-bar-height&#xff0c;小程序这个值是25px&#xff0c;app则根据实际情况去变化 如下&#xff1a; //头部导航栏 <view class"header"> </view…

【算法题】动态规划中级阶段之最长回文子串、括号生成、跳跃游戏

动态规划中级阶段 前言一、最长回文子串1.1、思路1.2、代码实现 二、括号生成2.1、思路2.2、代码实现 三、跳跃游戏 II3.2、思路3.2、代码实现 总结 前言 动态规划&#xff08;Dynamic Programming&#xff0c;简称 DP&#xff09;是一种解决多阶段决策过程最优化问题的方法。…

加速你的容器管理!轻松安装kubeadm、kebelet和kubectl!

1 kubernetes镜像切换成国内源 访问 阿里云镜像&#xff1a; M1M2芯片的arm64架构需要更改&#xff1a; cat > /etc/yum.repos.d/kubernetes.repo << EOF [kubernetes] nameKubernetes baseurlhttps://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_6…

Nginx【概述、应用场景、环境准备、下载与安装、目录详解、】(一)-全面详解(学习总结---从入门到深化)

目录 Nginx概述 Nginx 四大应用场景 为什么用Nginx 环境准备 Nginx下载与安装 Nginx目录详解 Nginx概述 Nginx是一款轻量级的Web服务器、反向代理服务器&#xff0c;由于它的内存占用少&#xff0c;启动极快&#xff0c;高并发能力强&#xff0c;在互联网项目中广泛应用。Ngi…

Linux基础:Vim编辑器实用指南

前言 Linux基础是学习云原生的重中之重&#xff0c;如果你还不知道学习路线可以参考&#xff1a; 耗时3个月&#xff0c;线下访谈30 csdn大佬&#xff0c;规划出了我的云原生学习路线 文章目录 前言vim的介绍vim的四种模式1. 插入模式1.1 进入插入模式&#xff1a;1.2 退出插入…

layui实现选择框搜索(下拉搜索)功能

1.可以使用官方介绍的方法&#xff0c;适用于form表单内的下拉搜索&#xff0c;外层需要使用layui-form样式&#xff0c;select标签内添加lay-search“”&#xff0c;此方法若外层不添加layui-form无法实现搜索功能&#xff0c;如下所示&#xff1a; 2.下面是另一种形式的下拉选…

【GESP】2023年06月图形化一级 -- 小猫寻宝

文章目录 小猫寻宝1. 准备工作2. 功能实现3. 设计思路与实现&#xff08;1&#xff09;角色、舞台背景设置a. 角色设置b. 舞台背景设置 &#xff08;2&#xff09;脚本编写a. 角色&#xff1a;Catb. 角色&#xff1a;Crystal 4. 评分标准 小猫寻宝 1. 准备工作 &#xff08;1&…

kafka生产者api和数据操作

Kafka 生产者 发送流程 消息发送过程中涉及到两个线程——main线程和Sender线程 main线程 使用serializer&#xff08;并非java默认&#xff09;序列化数据&#xff0c;使用partitioner确认发送分区 在main线程中创建了一个双端队列RecordAccumulator&#xff0c;main线程将…

从0到1搭建spring cloud alibaba +springboot+nacos+dubbo微服务

版本关系&#xff1a; spring cloud alibaba各组件对应关系 创建父工程&#xff0c;pom.xml配置如下&#xff1a; 由以上版本对应关系&#xff1a; springboot版本&#xff1a;2.3.2.RELEASE spring cloud 版本选择&#xff1a;Hoxton.SR9 spring cloud alibaba版本选择&#…

【UE5 Cesium】02-Cesium for Unreal 添加在线数据集

上一篇&#xff1a; 【UE Cesium】01-在虚幻5中使用Cesium 步骤 1. 点击“connected to Cesium ion as xxx” 在弹出的网址中点击“Asset Depot”&#xff08;资产仓库&#xff09; 找到“Melbourne Photogrammetry”点击添加&#xff0c;添加到你的账户中。&#xff08;这里我…

关于我花了一个星期学习微信小程序开发、并且成功开发出一个商城项目系统的心得体会

前言 一直做的PC端的项目开发&#xff0c;想做一下手机端的开发。后端基本上是不用怎么变化&#xff0c;主要变化的是前端&#xff0c;前端网页运行的地方不同&#xff0c;一个运行在手机&#xff0c;一个运行在PC网页上。微信小程序的开发和Vue框架开发有诸多相似之处&#xf…

smardaten用户手册全新发布!5个超实用的使用技巧(建议收藏!)

社区版发布后&#xff0c;很多用户自行下载安装使用&#xff0c;我们收到了一些客官关于产品文档的吐槽和建议~~于是&#xff0c;我们重新编排了用户手册&#xff0c;来帮助大家更快、更好、更简单的上手无代码开发。今天睿睿来跟大家分享用户手册更新点&#xff0c;以及如何使…