一步一步写线程之一简单的开始

一、多线程

多线程不管是在前面的文章分析中还是在网上还是大书籍上,学习C/C++多线程编程是无法绕过的,即使使用别人封装好的框架,包括使用STL的一些库,如果仅仅是简单的应用,可能也就过去了。不过,稍微复杂的一些应用,其实就需要对多线程的应用有深层次的理解。
尤其在使用一些封装库时,特别要注意库的一些注意事项,往往这些注意点是应用BUG的重要原因。比如std::async中std::future返回值如果控制不好,异步就可能变成了同步。所以说多线程要想写好,不但要会用一些库一些API,更要懂得这些库的底层原理,直到这个库调用的不同的平台,封装的是哪个OS的系统函数。如果再展开到并发和并行,更得需要了解相关OS的相关进程线程的调度知识等等。这些都是写多线程的开发者需要一步步学习的目标。不过在这里,只就时论事,只讲多线程,与OS相关的知识,用到就展开分析一下。
这个系列更侧重于线程的应用,而非基础知识的普及,所以如果在示例的一些源码代码中不清楚的基础的用法,需要去查一下前面的多线程的基础知识的文章或者自己行在网上查找一些相关知识。

二、线程的运用

多线程的应用其实是一个非常重要且普遍的应用。协程的编程目前看来应该是被排除到了更高的应用层上,也就是说,想用好协程,更多的是纯上层应用了。线程被迁移到了一个中间层的库应用。说得再深入一些,协程的普及,可能会让开发者写并发变得简单但同样大幅降低了技术门槛,这意味着什么,以前不明白的,这两年应该都懂了。
多线程的应用一般会和异步IO共同使用,有的人在网上说多线程和异步有什么不同,这就说汽车和钢铁有什么不同一样,这本来就是两回事。说多了,扯回来。
多线程的应用非常广泛,图像处理、数据读写、IO通信和时间控制等等,都可以用到。但正如已经分析过的一样,用的方法不一样,那么产生的结果也不一样。单纯的多线程读写操作不涉及到数据互斥没有什么难度。举个简单的例子,写十个线程,读十个不同的文件,这和写普通的非线程代码没有本质不同,可能只是套上了十个线程的壳子。但是如果这十个线程需要同时把读到数据写到一个缓冲区内,根据不同情况来覆盖或者追加相关数据,这就需要谨慎的处理了。否则数据很可能不是丢失就是多存储了。
另外,如果只有五个线程来处理十个文件呢?如果这十个文件大小不一,有的非常大,有的非常小?那么小文件读取完成后,这个线程不就空闲了么?多线程不还是单线程么。再细分一下,大文件可不可以切成段,在别的线程读完成文件后去读这些分段的大文件来加速读取的速度呢?这都是多线程需要解决的现实问题。
很多问题,在学习多线程编程时,是很难想到的或者说遇到实际问题不知道怎么下手,这其实就是学无法致用的一个典型的表现。在这个系列中,就把这些多线程的用法与实际的情况结合起来,进行一一的分析。

三、例程

做为简单的开始,本篇不做多么复杂的例程,只是把刚刚提到std::async遇到的同步问题展现一下以及相关的处理办法:

#include <iostream>       
#include <future>         
#include <chrono>int getData(int x) {std::cout << "async thread run start!"<<std::endl;std::this_thread::sleep_for(std::chrono::milliseconds(6000));std::cout << "async thread run end!" << std::endl;return x;
}int main()
{std::async(std::launch::async, getData, 100);std::cout << "go to ..."<<std::endl;return 0;
}

运行结果:

async thread run start!
async thread run end!
go to ...

你会发现运行的结果并不是期房的两个线程并行执行,而执行完async中的线程,才回头执行主线程的函数。什么原因呢,在std::async中有下面的话:
“If the std::future obtained from std::async is not moved from or bound to a reference, the destructor of the std::future will block at the end of the full expression until the asynchronous operation completes, essentially making code such as the following synchronous”
在std::future的析构函数中:
“these actions will not block for the shared state to become ready, except that they may block if all of the following are true:
the shared state was created by a call to std::async,
the shared state is not yet ready, and
the current object was the last reference to the shared state.”
在下面还有一句话,意思是说只在运行策略为“ std::launch::async ”才会产生这种情况。
所以通过上述两个说明就明白了,在std::async中,std::future的临时变量会在没有被移动或者引用情况下一直阻塞到异步计算完成,所以这句话也就给了解决方法:

auto d = std::async(std::launch::async, getData, 100);

只需增加上面的返回值处理即可,延长一下std::future的生命周期至期望的位置即可。用别人的东西,就得服别人的套路,一个不小心,就会吃亏上当。不过话又说回来,想省事,吃点亏也应该,对吧。

四、总结

从简单开始,不忘初心,朝着实际应用不断的前进。多线程编程属于那种入门容易,写好难,精通更难的一种编程技术,真正的生产上,大牛们被憋住当场打脸的情况也不少见。总之一句话,多看书,多实践,多应用。小心写代码,防御性编程,少引入BUG比如事后调试定位要更容易做到一些。

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

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

相关文章

VBA_MF系列技术资料1-237

MF系列VBA技术资料 为了让广大学员在VBA编程中有切实可行的思路及有效的提高自己的编程技巧&#xff0c;我参考大量的资料&#xff0c;并结合自己的经验总结了这份MF系列VBA技术综合资料&#xff0c;而且开放源码&#xff08;MF04除外&#xff09;&#xff0c;其中MF01-04属于定…

[Linux] 用LNMP网站框架搭建论坛

一、nginx在其中工作原理 原理&#xff1a; php-fpm.conf是控制php-fpm守护进程 它是php.ini是一个php解析器 工作过程&#xff1a; 1.当客户端通过域名请求访问时&#xff0c;Nginx会找到对应的虚拟主机 2. Nginx将确定请求。 对于静态请求&#xff0c;Nginx会自行处理…

结构体和位段

结构体&#xff1a; C语言中&#xff0c;我们之前使用的都是C语言中内置的类型&#xff0c;比如整形&#xff08;int&#xff09;、字符型&#xff08;char&#xff09;、单精度浮点型&#xff08;float&#xff09;等。但是我们知道&#xff0c;我们现实世界中&#xff0c;还…

聊聊spring.mvc.servlet.load-on-startup

序 本文主要研究一下spring.mvc.servlet.load-on-startup spring.mvc.servlet.load-on-startup org/springframework/boot/autoconfigure/web/servlet/WebMvcProperties.java ConfigurationProperties(prefix "spring.mvc") public class WebMvcProperties {//.…

json精讲

本文介绍json的规范及javascript和java对数据的交换读取 1. json介绍1.1 json简介1.2为什么使用 JSON&#xff1f; 2. json规范2.1基础规范2.2 key值为-字符串、数字、布尔值2.3 key值为对象Object2.4 key值为数组2.5 json本身就是一个数组 3.javascript操作json3.1 javascript…

WPF(Windows Presentation Foundation) 的 Menu控件

WPF&#xff08;Windows Presentation Foundation&#xff09;的 Menu 是一种用于创建菜单的控件。菜单通常位于应用程序窗口的顶部&#xff0c;并提供了一组命令或选项&#xff0c;用于导航到不同的功能区域、执行特定的操作或访问特定的功能。 Menu 控件是 WPF 中的一个容器…

2、关于使用ajax验证绕过(实例2)

ajax原理我上一篇有写过&#xff0c;参考&#xff1a;1、关于前端js-ajax绕过-CSDN博客 一、实例环境&#xff1a; 为手机上的某一割韭菜app 二、目的&#xff1a; 实现绕过手机验证码&#xff0c;找回密码 三、工具&#xff1a; bp代理 四、验证步骤如下&#xff1a; …

ECU安全学习网站和书籍介绍

ECU安全是指关注和保护汽车电子控制单元&#xff08;ECU&#xff09;的安全性和防护措施。ECU是现代汽车中的关键组件&#xff0c;它负责监控和控制车辆各种系统的运行&#xff0c;如发动机、制动、转向等。ECU安全的重要性在于防止恶意攻击者操控或干扰车辆的操作。 ECU安全涉…

hive自定义函数及案例

一.自定义函数 1.Hive自带了一些函数&#xff0c;比如&#xff1a;max/min等&#xff0c;但是数量有限&#xff0c;自己可以通过自定义UDF来方便的扩展。 2.当Hive提供的内置函数无法满足你的业务处理需要时&#xff0c;此时就可以考虑使用用户自定义函数。 3.根据用户自定义…

GitHub为Rust语言添加了供应链安全工具

GitHub的供应链安全特性包括咨询数据库、Dependabot警报和依赖关系图现在可以用于Rust Cargo文件。 为了帮助Rust开发人员发现和防止安全漏洞&#xff0c;GitHub已经为快速增长的Rust语言提供了供应链安全特性套件。 这些特性包括GitHub Advisory Database&#xff0c;它已经有…

构建外卖系统:使用Django框架

在当今数字化的时代&#xff0c;外卖系统的搭建不再是什么复杂的任务。通过使用Django框架&#xff0c;我们可以迅速建立一个强大、灵活且易于扩展的外卖系统。本文将演示如何使用Django构建一个简单的外卖系统&#xff0c;并包含一些基本的技术代码。 步骤一&#xff1a;安装…

shell的条件测试

shell 的条件测试 概述 条件测试是 shell 编程中非常重要的一个概念&#xff0c;它允许我们根据某个条件是否满足&#xff0c;来选择执行相应的任务。 条件测试的语法 shell 中的条件测试语法如下&#xff1a; [ 条件表达式 ]如果条件表达式为真&#xff0c;则返回 0&…

CentOS 7.9--离线安装python3.9.18+virtualenv-20.25.0

# 想在centos6.x 上安装新版本的python&#xff0c;但是担心在用系统的环境被破坏&#xff0c;所以需要安装python虚拟环境&#xff0c;然后就找到自用的aliyun主机先测试下离线安装&#xff0c;在用6.X环境是没有互联网的&#xff0c;必须需要离线安装。 1. 下载对应python源…

力扣解题之保姆教程:(1)两数之和(代码详解)

题目描述 给定一个整数数组 nums 和一个整数目标值 target&#xff0c;请你在该数组中找出 和为目标值 target 的那 两个 整数&#xff0c;并返回它们的数组下标。 假设每种输入只会对应一个答案。但是&#xff0c;数组中同一个元素在答案里不能重复出现。你可以按任意顺序返回…

Django模板

以下是一个简单的Django模板示例&#xff1a; <!DOCTYPE html> <html><head><title>{{ title }}</title></head><body><h1>{{ heading }}</h1><p>{{ content }}</p></body> </html>一、模板的…

波奇学Linux:父子进程和进程状态

vim编辑器&#xff0c;编写一个程序模拟进程 在vim中查看sleep函数 底行模式输入 写个Makefile自动运行波奇学Linux:yum和vim-CSDN博客 运行程序 PID和PPID 查看进程目录信息 实际有过滤出来有两个&#xff0c;一个进程本身一个是grep程序&#xff0c;通过 -v grep过滤走含gre…

新版Android Studio 正则表达式匹配代码注释,删除注释,删除全部注释,IntelliJ IDEA 正则表达式匹配代码注释

正则表达式匹配代码注释 完整表达式拼接Android Studio 搜索匹配【IntelliJ IDEA 也是一样的】 完整表达式拼接 (/*{1,2}[\s\S]?*/)|(//[\x{4e00}-\x{9fa5}].)|(<!-[\s\S]?–>)|(^\s\n)|(System.out.println.*) 表达式拆解&#xff0c;可以根据自己需求自由组合&#x…

Mybatis、Mybatis整合Spring的流程图

Mybatis 注意MapperProxy里面有invoke方法&#xff0c;当进到invoker方法会拿到 二、mybatis整合Spring 1、当我们的拿到的【Dao】其实就是【MapperProxy】&#xff0c;执行Dao的方法时&#xff0c;会被MapperProxy的【Invoke方法拦截】 2、图上已经标注了MapperProxy包含哪些…

力扣:200. 岛屿数量(Python3)

题目&#xff1a; 给你一个由 1&#xff08;陆地&#xff09;和 0&#xff08;水&#xff09;组成的的二维网格&#xff0c;请你计算网格中岛屿的数量。 岛屿总是被水包围&#xff0c;并且每座岛屿只能由水平方向和/或竖直方向上相邻的陆地连接形成。 此外&#xff0c;你可以假…

STM32-TIM定时器中断

目录 一、TIM&#xff08;Timer&#xff09;定时器简介 二、定时器类型 2.1基本定时器结构 2.2通用定时器结构 2.3高级定时器结构 三、定时中断基本结构 四、时序图分析 4.1 预分频器时序 4.2 计数器时序 4.3 计数器无预装时序&#xff08;无影子寄存器&#xff09; …