这里先给大家分享一个小故事:

在我刚开始参加工作的那年,公司安排我开发一款即时通讯软件(IM,类似于 QQ 聊天软件),在这之前我心里也知道如果多线程操作一个整型值是要加锁的,但是当时为了图代码简便,而且在实际调试的时候,没有加锁的代码也从来没出过问题。于是我就心存侥幸了,觉得对整型值加锁真是多此一举。

我们的软件有类似于 QQ 这种单人聊天功能,每个用户都有一个整型的 userid,问题就出在这里。当时公司的老板和他妻子也使用这款软件,问题来了:有一天早上老板在这个软件上给他妻子发了一段亲密的话。问题来了,由于多线程操作他妻子的 userid 没加锁,最终变成了另外一个人的 userid,而这个 userid 恰好是我的账户。于是老板发给他妻子的聊天内容就被发给我了

我当时看到聊天内容很奇怪,还回复了他一句,并且还带上了我自己的姓名……事情的结果,可想而知了,老板非常尴尬也非常生气……从那以后,老板看我的眼神都是怪怪的。我自知理亏,再也不侥幸了,凡是多线程读写整型变量都养成加锁的好习惯

这是我曾经犯过的错误,也就是所谓的线程安全问题。“年轻”时的我,当时不明白为什么一个整型变量在多线程操作时存在安全问题,进而引起业务上的错乱问题。

很多年以前的时候,技术面试的时候面试官经常会问“程序什么时候需要开启新的线程”这样的问题,那个时候多核 CPU 才刚开始普及,很多人也是才开始逐渐接触多线程技术。而如今多核 CPU 和多线程编程技术已经是下里巴人的技术了。

因此“程序什么时候需要开启新的线程”这一类问题,简单解释一下,就是为了提高解决问题的效率,毕竟大多数情况下,多个 CPU 并行做一件事总比单个 CPU 做要快很多。
然而,多线程程序虽然强大,但也让原来的程序执行流程变得复杂和具有一定的不确定性,比如带来资源的竞态问题,初学者或许意识不到带来的后果,往往不能够很好处理这个问题,帮助学习多线程编程的初中级读者,理清多线程程序的执行原理、脉络是我写专栏的创作初衷之一。
由于各种库和运行环境对操作系统多线程接口的封装,很多技术开发者做了很多年的开发,仍然只是个界面或者仅知道调用库的“业务”程序员,他们只能面向搜索引擎编程,遇到稍微复杂一点的多线程逻辑就不知如何下手了。

本专栏将从操作系统原理的角度介绍多线程技术的方方面面,从基础的知识到高级进阶,它们是笔者这些年工作的经验总结和踩坑之后的教训。

本专栏的内容主要分为以下三大方面。
操作系统层面上关于多线程和多线程协作的接口原理

无论是哪种编程语言和库,其最终都是要运行在操作系统上的,应用程序本身的特性应该是决定采用何种编程工具的最主要因素,但是无论你采用什么样的编程语言,通过了解操作系统 API 从而深入理解操作系统的工作原理,这本身就有很重要的意义。

操作系统是一个非常复杂的系统,在 API 之上加一层编程语言并不能消除其复杂性,最多不过是把复杂性隐藏起来而已。说不定什么时候,复杂的那一面迟早会蹦出来拖你的后腿,懂得系统 API 能让你可以更快地挣脱困境。

因此,针对多线程编程,本专栏将详细地介绍 Windows 和 Linux 操作系统层面上提供的各种多线程接口,理解并熟悉它们的使用后,读者在接触或者学习其他语言或者库提供的多线程功能时,可以快速地上手和掌握。

以协程这一技术为例,虽然协程是计算机操作系统原理之一,但是我们所接触的大多数操作系统并没有从系统层面上支持协程这一技术

而像 Golang 这一类语言是提供协程功能的,那这一类语言是如何支持的?如果你对操作系统的线程有着深入的了解,你也不难想明白:
线程是操作系统的内核对象,当多线程编程时,如果线程数过多,就会导致频繁地上下文切换,这些对性能是一种额外的损耗。
协程,是在应用层模拟的线程,它避免了上下文切换的额外损耗,同时又兼顾了多线程的优点,简化了高并发程序的复杂度。

再例如,线程局部存储技术是我们常用的一项多线程技术,它的存在让每个线程可以有自己私有存放数据的空间。那线程局部存储技术是如何实现的呢?本专栏中会庖丁解牛地介绍线程局部存储是什么以及它的实现原理。

基于操作系统多线程理论衍生出来的一些扩展理论模型和应用

正因为存在多线程编程,所以有了线程池模型,据我了解,“线程池”的实现和原理应该是多线程编程新手问的、聊的最多的一个技术点了。

本专栏会带领读者利用各种操作系统提供的线程同步对象来实现一个线程池,进而引出生产者消费者理论模型,再进一步升华,引出所谓的消息中间件,如 Kafka、RabbitMQ。

对于技术方案,我们不推崇重复造轮子,但是一定要具有重复造轮子的能力和了解轮子的制造原理。有了这项能力之后,在使用一些开源的消息中间件时,我们因为“知其然、知其所以然”才会把这些软件在项目中用得更好。

本专栏中会详细地介绍多线程操作整型变量非线程安全的原因以及解决方案。掌握了这些,你在学习像 Java 语言时,就明白了为什么 JDK 在操作一个整型变量时提供 AtomicInteger 这样的类了。

和多线程相关的,一些实际开发中的技巧和经验
如果你是一名开发者,那么曾经或许会为下面一些问题而头痛过,这些问题或许你在面试时被面试官问到或者在实际开发中遇到过:
  • 进程的 CPU 使用率过高如何查找原因并解决?

  • 如何让一个程序只允许使用者运行一个实例?

  • 在实际开发中,避免死锁有哪些可以遵循的规则?

  • 什么是条件变量的虚假唤醒?虚假唤醒会带来什么问题?如何解决?

  • 如何设计高效的线程池和队列模型?

  • 如何在线程函数中访问类的成员变量和函数?

诸如此类实际开发中经常遇到问题,实在太多了,这里就不一一列举了。本专栏在保持主干脉络介绍的同时,也会穿插介绍一些与多线程相关的开发技巧和经验。

当然,多线程问题本来就比较复杂,尤其是本专栏同时介绍 Windows 和 Linux 两个操作系统平台的接口,在实际编写程序时,由于操作系统提供的 API 不一样,为了跨平台,我们不得不写许多跨平台代码。好在,C++ 11/14 标准给 C++ 引入了大量的多线程类和库,本专栏也会详尽地介绍它们的用法。

扫码查看《C/C++多线程编程精髓》专栏详情
以下是专栏的主要内容导图:
内容亮点:
  • 解析操作系统 API 层的多线程编程原理

  • 展示 Windows 和 Linux 操作系统的基本原理

  • 讲解线程间各种同步原语的适用场景、优缺点

  • 贯穿实际开发中的问题定位与排查

你将获得:
  • 彻底掌握多线程编程原理和编码经验

  • Windows 和 Linux 操作系统的基本原理

  • 线程之间各种同步原语的适用场景和优缺点

  • 相关编程惯用法和手段技巧

  • 了解 Java、Go 等上层语言运行时环境提供的功能是如何基于操作系统 API 实现的

  • 实际开发中一些问题定位与排查

由于操作系统调度线程时的不确定性,同样的逻辑可能在不同机器、不同时刻有不同的行为表现,也因此增加了排查和定位问题的难度。这是在学习和开发多线程程序时不得不面临的问题。

建议读者将专栏各个章节中的代码示例都实际在机器上运行一遍,认真、准确地理解每一个多线程同步原语的适用场景和性能优缺点。只要透彻地理解了这些操作系统提供的基础多线程同步原语,在面对它们的衍生物(如线程池、消息队列、协程技术等)时可以更快地学习和用好。

操作系统提供的 API 接口一般在相当长的时间内会保持不变的(至少保持向后兼容),一经学会,终生受用。在新技术新思想层出不穷、令人应接不暇时,掌握了操作系统层面的 API 和其设计思想原理,可以以不变应万变

最后,多线程编程在现代软件开发中是如此的重要,以至于熟练使用多线程编程是一名合格的后台开发人员的基本功,它是如此的重要,希望本专栏能帮助你掌握它,愿它能让你彻底告别多线程编程烦恼。

点击阅读原文,特价订阅专栏

多线程编程是后台开发人员的基本功相关推荐

  1. 为什么技术团队领导者多是后台开发人员

    先别急着往下拉文章,现在思考一个问题:你现在的软件开发团队或之前的团队,带领团队的人处于软件开发职能的哪一个岗位?产品经理,UI设计还是前端开发,后台开发,测试人员,运维人员?(专业团队除外) 给出上 ...

  2. 作为一名后台开发人员,你必须知道的两种过滤器

    前段时间在网上看到一篇关于过滤器的文章,感觉非常硬核.又因为这个知识点是后台开发中必知必会的技能点,所以分享给大家,一起学习,共同进步! 下面是正文. 对于海量数据处理业务,我们通常需要一个索引数据结 ...

  3. [转]关于多线程并发:每个开发人员都应了解的内容(转自Mainz's)

    Concurrency: What Every Dev Must Know About Multithreaded Apps 本文讨论: 多线程和共享内存线程模型 争用及并发访问如何能够打破不变量 作 ...

  4. 后台开发人员面试内容——JVM虚拟机(四)

    一.Java类加载机制 类从被加载到虚拟机内存中开始,到卸载出内存,它的整个生命周期包括:加载(Loading).验证(Verification).准备(Preparation).解析(Resolut ...

  5. 综合应用WPF/WCF/WF/LINQ之八:后台开发人员的Solution

    该Solution的所有Project如下: 下面对各个Project一一进行介绍: Eallies.OA.BLL:用于系统中BLL层的所有类的存放.该Project可以采用Eallies.Utili ...

  6. 后台开发人员面试内容——数据库(二)

    数据库锁分类 从数据库系统角度分为三种:排他锁.共享锁.更新锁. 从程序员角度分为两种:一种是悲观锁,一种乐观锁. 1.乐观锁和悲观锁 1).乐观锁:每次不加锁,假设没有冲突去完成某项操作,如果因为冲 ...

  7. 后台开发人员面试内容——操作系统(一)

    操作系统 并发编程的3个基本概念 1.原子性:即一个操作或者多个操作 要么全部执行并且执行的过程不会被任何因素打断,要么就都不执行 2.可见性:指当多个线程访问同一个变量时,一个线程修改了这个变量的值 ...

  8. 2018平安科技春季校招后台开发人员面试经历

    步骤 1.在线IQ.EQ测试,EQ测试题量大,选正能量.积极的选项即可. 2.通过1之后隔天会收到在线笔试邀请,附笔试地址链接.牛客网的题,12道单选,4道多选,两道编程,内容上涵盖了网络基础,jav ...

  9. JAVA实现网络多线程编程小游戏开发

    总结一下JAVA本学期的大作业. 实验总结:五子棋是一个很简单的游戏,但是如果认真对待,一个代码一个代码的去研究,会收获到很多知识,会打好学习基础.方便以后开发更高.更难的项目时打下稳固的基础.在自己 ...

最新文章

  1. LabVIEW做一款科学计算器
  2. windows系统无法创建文件共享
  3. 第一个Mybatis程序示例 Mybatis简介(一)
  4. java jsp w3c报错_JSP JavaBean
  5. 单片机编程php,STC单片机内部FLASH读写程序(最新整理)
  6. oracle 11g ORA-12541: TNS: 无监听程序 (DBD ERROR: OCIServerAttach)
  7. asp.net core 自定义 Content-Type
  8. 铺铜过孔不要十字_谈谈商周青铜器上圈足的镂孔现象
  9. HDU - 5878 A - I Count Two Three H 技巧枚举
  10. python 类继承和组合_python类与对象的组合与继承
  11. 通过安装扩展让 KDE Plasma 5 桌面看起来感觉就像 Windows 10 桌面
  12. Android 系统(138 )---Mtk平台 Android 打包解包*.img ,修改system.img 参数
  13. 计算机算法设计与分析 递归实现快速排序和随机化实现快速排序
  14. _2020年10个最好的Linux发行版本
  15. hadoop1.1.2集群安装指南
  16. JSP听课笔记(一)
  17. Ruby 2.0 发布首个预览版
  18. eeglab导出图片
  19. 架构真经深有体会、感触很深
  20. 刚刚想起猴子布丁,查了点资料,自己实践了下,记录汇总下。

热门文章

  1. 为ASP.NET 2.0网站生成唯一程序集
  2. [Ubuntu] 16.04 上使用 pip 安装 mysqlclient
  3. html设置referer防盗链,referer与防盗链
  4. 如何以源码安装mysql_CentOS以源码方式安装MySQL
  5. [SQL实战]之获取当前薪水第二多的员工的emp_no以及其对应的薪水salary
  6. 中国内窥镜干燥存放柜市场趋势报告、技术动态创新及市场预测
  7. js 浮点数精度问题 可以用accounting.js解决
  8. asp.net数据库连接php代码,ASP.NET 数据库连接
  9. linux pipe 阻塞,Linux pipe():從管道中讀取數據並不總是能夠解阻塞寫入器
  10. JAVA Swing GUI设计 WindowBuilder Pro Container使用大全5——JToorBar使用