提示:本文的所有代码由C语言实现,经过测试,C++的多线程操作也会遇到同样的问题。多线程库用的是pthread.h,操作系统是win10。windows下的pthread.h安装,可以参考下这篇文章:vs2017如何配置pthread环境

文章目录

  • 前言
  • 一、多线程代码
    • 1.带有返回值的多线程代码
    • 2.结果展示
  • 二、问题修复
    • 1.修改子线程调用方法
    • 2.结果展示
  • 总结

前言

最近因为工作需要,调研了一下C语言的多线程使用。在测试常用功能的时候遇到这么一个诡异的问题,通过结构体获取返回值的时候,多线程操作变慢了。经过一天的努力,最终解决了这个问题。以下是对该问题的记录。


一、多线程代码

1.带有返回值的多线程代码

下面代码包括生成一个5行1000万列的随机数组,然后分别使用多线程的和单线程的方法对每一行进行求和。其中多线程的参数是一个结构体,包括要求和的数组和一个sum返回值。

#include <stdio.h>
#include <time.h>
#include <pthread.h>  //定义随机数组的行和列
#define ROW   5
#define COL 10000000//获得随机数组
int ** getRandom()
{printf("生成%dX%d的随机数组\n", ROW, COL);int  **r;r = (int **)malloc(ROW * sizeof(int));for (int i = 0; i < ROW; i++) {r[i] = (int *)malloc(COL * sizeof(int));}srand((unsigned)time(NULL));for (int i = 0; i < ROW; i++) {for (int j = 0; j < COL; ++j){r[i][j] = rand();}}printf("随机数组生成完毕\n\n");return r;
}//定义传入线程的结构体
typedef struct TagValue
{int *arr;long long sum;
} Tag;//子线程调用求和方法
void* threadSum(void *d) {Tag *v = (Tag*)d;int *arr = v->arr;for (int i = 0; i < COL; i++) {v->sum += *(arr + i);}
}//多线程主方法
void  testThreadTime(int **r) {//计算多线程运行时间clock_t start, end;//传入参数结构体Tag res[ROW];//线程id号pthread_t ths[ROW];//记时开始start = clock();for (int i = 0; i < ROW; i++) {res[i].arr = r[i];res[i].sum = 0;//开启子线程int ret_thrd1 = pthread_create(&ths[i], NULL, (void *)&threadSum, (void *)&res[i]);// 线程创建成功,返回0,失败返回失败号if (ret_thrd1 != 0) {printf("子线程%d创建失败\n",i);}else {printf("子线程%d创建成功\n",i);}}//增加join函数,使主线程等待子线程都结束for (int i = 0; i < ROW; i++) {pthread_join(ths[i], NULL);}//打印返回值printf("多线程的执行结果是:\n");for (int i = 0; i < ROW; i++) {printf("%lld\n", res[i].sum);}printf("主线程执行完毕\n");//计时结束end = clock();printf("Time Used: %f\n\n", difftime(end, start));
}//非多线程对照方法
void  testNoThreadTime(int **r) {clock_t start, end;//int **r = getRandom();long long res[ROW];memset(res, 0, ROW * sizeof(long long));start = clock();for (int i = 0; i < ROW; i++) {for (int j = 0; j < COL; j++) {res[i] += r[i][j];}}end = clock();printf("对照组执行结果是:\n");for (int i = 0; i < ROW; i++) {printf("%lld\n", res[i]);}printf("Time Used: %f\n\n", difftime(end, start));
}int main() {int **r = getRandom();testThreadTime(r); testNoThreadTime(r);  getchar();return 0;
}

2.结果展示


可见多线程不但没有减少计算时间,反而增加了很多。

二、问题修复

1.修改子线程调用方法

出现问题是threadSum函数里的这句代码v->sum += *(arr + i),这句代码对主线程里声明的地址内容进行了大量的修改操作。按照下面方式修改,声明临时变量sum,求和在临时变量sum中进行,只需进行简单的修改,多线程变慢的问题就解决了

void* threadSum(void *d) {Tag *v = (Tag*)d;int *arr =v->arr;long long sum = 0;for (int i = 0; i < COL; i++) {sum+=*(arr + i);}v->sum = sum;
}

2.结果展示


修改之后,多线程已经可以正常提升计算效率了。

总结

在C/C++的多线程使用过程中,一定要注意在子线程中对传入地址的写操作。频繁的跨线程写操作,会带来效率的大幅降低。

记录一个使C/C++多线程无法加速计算的问题相关推荐

  1. 记录一个C++多线程的坑

    记录一个C++多线程的坑 VS2019报错 解决方案: 错误代码 修改方案: 写在最后,发牢骚 VS2019报错 1>C:\Program Files (x86)\Microsoft Visua ...

  2. 复习Java第二个项目仿QQ聊天系统 03(两种通信类、登录以及注册功能完善) Java面试题并发编程相关知识生活【记录一个咸鱼大学生三个月的奋进生活】025

    记录一个咸鱼大学生三个月的奋进生活025 复习Java(仿QQ聊天系统03两种通信类.登录以及注册功能完善) TcpSocket类(与服务器进行通信) Server类(服务器类) TcpMessage ...

  3. 写一个使两个整数进行交换的方法(不能使用临时变量) 【前端每日一题-27】...

    写一个使两个整数进行交换的方法(不能使用临时变量) 这道题是一个比较有意思的题,记录于此. var a=10; var b=20;...不用临时变量让a和b交换console.log(a); cons ...

  4. Operating System-Thread(5)弹出式线程使单线程代码多线程化会产生那些有关问题

    Operating System-Thread(5)弹出式线程&&使单线程代码多线程化会产生那些问题 本文主要内容 弹出式线程(Pop-up threads) 使单线程代码多线程化会产 ...

  5. 复习Java第一个项目学生信息管理系统 04(权限管理和动态挂菜单功能) python简单爬数据实例Java面试题三次握手和四次挥手生活【记录一个咸鱼大学生三个月的奋进生活】016

    记录一个咸鱼大学生三个月的奋进生活016 复习Java(学生信息管理系统04权限管理和动态挂菜单功能) 改写MainFrame的构造方法 新增LoginFrame的验证登录是否成功的代码 新增Logi ...

  6. 一个轻巧高效的多线程c++stream风格异步日志(一)

    一个轻巧高效的多线程c++stream风格异步日志 一个轻巧高效的多线程c++stream风格异步日志 前言 功能需求 性能需求 Logger实现 LogStream类 Logger类 LogStre ...

  7. 复习Java小球游戏代码分享Java面试题MySQL中常用的锁生活【记录一个咸鱼大学生三个月的奋进生活】021

    记录一个咸鱼大学生三个月的奋进生活021 复习Java小球游戏 游戏界面的代码 小球运动线程的代码 运行游戏的代码 运行结果 代码分享 学习Java面试题(MySQL中常用的锁) 照片分享 复习Jav ...

  8. 复习Java第二个项目仿QQ聊天系统 01(界面部分) Java面试题Redis的过期策略和内存淘汰策略生活【记录一个咸鱼大学生三个月的奋进生活】023

    记录一个咸鱼大学生三个月的奋进生活023 复习Java(仿QQ聊天系统01界面部分) 设置背景(ImgPanel)类 登录界面(LoginFrame)类 注册界面(RegisterFrame)类 好友 ...

  9. 把一个质量为M0 的物体加速到 时间慢100倍 需要多大能量

    洛伦兹系数  γ = 100: 运动时候的质量  M = γM0 速度   v = c*sqrt(1-1/γ2) E = 1/2 * m0c2  *γ* (1-1/γ2) 如果一个60kg 的人想要加 ...

最新文章

  1. vivado中设置多线程编译
  2. Ubuntu 16.04下减小/释放/清理VirtualBox虚拟硬盘文件的大小
  3. Crawler:基于urllib+requests库+伪装浏览器实现爬取国内知名招聘网站,上海地区与机器学习有关的招聘信息(2018.4.30之前)并保存在csv文件内
  4. 阿里巴巴如何改善开发人员在 K8s 上的体验?
  5. Winform中怎样设置ContextMenuStrip右键菜单的选项ToolStripMenuItem添加照片
  6. vc2010中设置ipch与sdf的位置
  7. 【渝粤题库】国家开放大学2021春3962金融营销基础题目
  8. 黑马程序员--ADO.Net中的知识点和难点
  9. Halcon中OCR的实现及关键函数解析
  10. WCF服务重构实录(中)
  11. Postfix配置QA
  12. 测试工具JMeter详细安装配置教程(保证一次安装成功)
  13. html 怎么让整体居中,html中表格整体居中 详解html里面如何让表格居中
  14. ps 命令 快捷键 知识点汇总
  15. 常来长安——西安游记(我愿称之为博物馆七日游)
  16. 海丽宾雅水疗服务App技术支持
  17. Android 饼形图
  18. 计算机的简史:从数字运算到强大的现代机器
  19. yolov5剪枝实战3: yolov5-slimming项目运行演示
  20. 袋鼠云日志助力云南某金融机构日志平台建设,实现核心业务系统运维智能化...

热门文章

  1. 网络通信原理与IP地址的分配原理,网络七层由下往上分别为物理层、数据链路层、网络层、传输层、会话层、表示层和应用层
  2. SecureCRT方向键不可用
  3. css —— 文字添加白色描边
  4. 分享7个比B站更刺激的老司机网站,别轻易点开
  5. (四)Vue之数据绑定
  6. 重要接口关键词搜索——item_search-按关键字搜索淘宝商品
  7. Spark的搭建及实现单词统计
  8. ppt幻灯片如何与母版背景一块复制到新幻灯片
  9. vue 报错avoid mutating a prop directly since the value will be overwritten whenever
  10. BIM模型文件下载——某幼儿园设计方案Revit模型