程序员修炼之道 10:并发

news2024/9/23 17:34:22

不记录,等于没读。

这里是我阅读《程序员修炼之道》这本书的记录和思考。


并发和并行代码曾经是很新奇的玩意,但现在已经是标配。

并发 :Concurrency,指的是两个或更多个代码段在执行过程中表现得像是在同时运行一样。
并行 :Parallelism,指的是两个或更多个代码段的确是在同一时刻一起运行(需要硬件多核支持)。

打破时域耦合

时域耦合 指的是时间。如果代码给几件事情强加一个顺序进来,而这个顺序对解决手头问题而言并非需要,就会发生 时域耦合 。如果想保持灵活性就不要这样。

时间 对我们来说有两个重要的方面:并发性 以及 次序 (事情在时间轴上的相对位置)。

时域耦合——在时间范畴上产生耦合:A 方法必须在 B 方法之前调用;一次只能运行一个报告;在按钮按下前必须等屏幕先重绘……这些方法不太灵活,也不太符合现实。

我们需要考虑并发性,并且考虑对时间依赖或顺序依赖解耦。利用 活动图 之类的工具来清理工作流们可以让我们知道哪些事情可以同时进行,哪些必须按照严格的顺序发生。这是设计工作的一部分

针对并发做设计所追求的东西是:找到那些耗时的活动,从中找出等待的操作,比如查询数据库、等待用户输入,在这些等待的间隙,去做一些更有意义的事情。

识别出哪些地方可以从并发和并行中受益知识第一步,接下来到了棘手的部分:如何安全地实现并发和并行。

共享状态是不正确的状态

你坐在最喜欢的餐厅。吃完主菜,问服务员还有没有苹果派。他回头看了看,看到陈列柜里有一个,说“有的”。你点了它,心满意足地长出一口气。
与此同时,在餐厅的另一边,另一位顾客问另一个服务员同样的问题。她也看了看,确认有一个,然后顾客点了单。
总会有一个顾客会失望的。

问题出在共享状态。餐馆里的每一位服务员都查看了陈列柜,却没有考虑到其他服务员。这两个服务员在并行操作,他们对苹果派的数量的获取和更新,均不是 原子操作

信号量 和其它形式的 互斥量 可以让行为具有原子操作。简而言之,它们是一个在同一时间只能让一个人持有的东西。

比如可以在苹果派的陈列柜上放一个塑料小妖精(充当一个信号量)。任何服务员在卖苹果派之前,必须先把小妖精抓在手里,直到把苹果派送到顾客桌子上才可以把小妖精放回原处。

这种方法可行,但也存在一些问题,就是所有服务员都必须严格遵循纪律才行得通。如果一个服务员故意或忘记使用小妖精,那么我们又会陷入混乱。这是因为将保护陈列柜访问权的责任委托给了使用它的人。

所以我们得换一种方法,让资源具备 事务性 。也就是对该资源的操作具有原子性。比如服务员在查看苹果派数量时,如果有,则直接获取一个苹果派,顾客如果点单,则将这个苹果派给顾客;如果顾客不想要了,再把苹果派放回陈列柜。

如果顾客既要苹果派又要冰淇淋,这就涉及更复杂的多资源分配。多资源分配处理不好就会引发死锁。书中推荐的方法是将多个资源放入一个模块,要么成功分配所有资源,要么分配失败。

任何时候,只要两个或多个代码块持有对同一个可变数据块的引用,就已经共享了状态。

Linux 环境中,当前目录 也是共享资源,在线程之间共享。任何修改当前目录的操作,都要注意。

随机故障通常是并发问题

Actor 模型

在共享资源环境中实现并发非常难,Actor 模型可以简化并发设计。

Actor 模型应该翻译成什么,书中翻译成“角色模式”,它和现实中的演员角色如何对应,我查了很久的资料,最后还是不知道。

Actor 模型是一个抽象模型,用于并发运算,并不绑定任何编程语言。在上一节,主要内容是讲述了 共享状态 会带来无穷的麻烦,而本节,则推荐使用 Actor 模型来管理并发状态,从而简化并发设计。

Actor 模型的推崇的哲学是:一切皆 Actor。

根据书中描述,Actor 具有以下特征:

  1. 一个 Actor 是一个进程,即一个独立的虚拟处理单元。
  2. 具有自己的本地私有 状态 (state)。
  3. 每个 Actor 都有一个 信箱 (mailbox) 。
  4. 当消息出现在信箱中且 Actor 处于空闲状态时,Actor 被激活并开始处理消息。
  5. Actor 会循环处理邮箱中的信息,直到邮箱为空,然后 Actor 进入休眠。

在处理消息的过程中,一个 Actor 可以有以下动作:

  • 可以创建其它 Actor。
  • 可以向它认识的 Actor 发送消息 ,并创建一个新状态,该状态将在处理下一条消息时成为当前状态。

使用 Actor 需要满足以下纪律:

  • 没有一件事是可控的。不能假设它是有序的。
  • 系统中 唯一 的状态,保存在消息和每个 Actor 的本地状态中。本地状态在 Actor 之外无法被读取。
  • 所有消息都是单向的,没有回应这个概念。如果希望 Actor 能返回一个回应消息,则需要在发送给 Actor 的消息中包含自己的邮箱地址,然后由 Actor 将回应作为另一条消息发送到该邮箱。
  • Actor 一次只会处理一条消息。

并发实在是太容易出问题了,所以就出现了 Actor 模型,用一系列规范来简化并发处理,它是在数学上可证明的(见 Gul Agha 的 1985 年学位论文)。






每一份打赏,都是对创作者劳动的肯定与回报。
千金难买知识,但可以买好多奶粉

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

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

相关文章

AD的3D模型格式是什么

AD通常指的是Altium Designer,这是一款用于电子设计自动化的软件,主要用于电路板的设计。在Altium Designer中,3D模型主要用于PCB(印制电路板)设计中的可视化,以便设计师能够在三维空间中查看组件和板的布局…

21:【stm32】定时器二:输入捕获

输出捕获 1、输出捕获的简介2、输入捕获原理2.1、输入滤波2.2、信号选择2.3、CCx事件和CCx中断 3、标准库编程 1、输出捕获的简介 定时器通过通道捕获输入电平的变化,而通道有CH1~CH4,这4个通道。 我们设定对通道CH3的输入电平进行捕获。假如CH3突然捕获…

Java排序算法详解

在Java编程中,排序算法是数据处理和算法设计中的基础且重要的部分。它们广泛应用于各种场景,如数据库管理、数据分析、图形界面排序等。掌握几种常见的排序算法对于提升程序效率和优化性能至关重要。本文将详细解析几种经典的Java排序算法,包…

OpenGL笔记二十之深度检测概念

OpenGL笔记二十之深度检测概念 —— 2024-08-25 晚上 bilibili赵新政老师的教程看后笔记 code review! 文章目录 OpenGL笔记二十之深度检测概念1.课程PPT截图2.运行3.代码 1.课程PPT截图 2.运行 3.代码 关键部分 main.cpp #include <iostream>#include "glfra…

【逐行注释】三维EKF的MATLAB代码|附下载链接

文章目录 程序概况源代码与注释运行结果代码块解析 程序概况 基于MATLAB的EKF&#xff08;扩展卡尔曼滤波&#xff09;代码解析。状态转移和观测都是非线性的&#xff0c;也就是说会涉及到雅克比矩阵的求解。我尽量将模型设计复杂一点&#xff0c;便于拿到手以后改成自己想要的…

C++类和对象(2)——拷贝构造函数

拷贝构造函数的语法 拷贝构造函数是构造函数的重载&#xff0c; 用于这种情况&#xff1a;用已经构造好的对象去给另一个对象初始化。 int main() {Date d1(2024, 8, 1);Date d2(d1);//用d1初始化d2return 0; } 我们以Date类为例子讲解一下。 class Date { public://全缺省…

.NET周刊【8月第3期 2024-08-18】

国内文章 Roslyn 简单实现代码智能提示补全功能 https://www.cnblogs.com/lindexi/p/18365261 相信有很多伙伴热衷于编写 IDE 应用&#xff0c;在 dotnet 系下&#xff0c;通过 Roslyn 友好的 API 和强大的能力&#xff0c;实现一个代码智能提示是非常简单的事情。本文将和大…

【互动直播】支付能力视角与年龄的调节作用—推文分享—2024-08-25

【今天的关键词是&#xff1a;“interaction” AND “live commerce”】 第一篇&#xff1a;通过信息技术的可供性&#xff08;IT affordance&#xff09;视角&#xff0c;直播电商的实用、社交和享乐三个维度的IT可供性如何影响购买意愿&#xff1b; 第二篇&#xff1a;研究…

凭借着“16连射”造就一个游戏角色的诞生

一、高桥名人的冒险岛起源 大约在 1986 年&#xff0c;Hudson 的所有人都很喜欢一款名为《神奇男孩》的街机游戏&#xff0c;公司内部有人建议将其改编成 Famicom 游戏。因此&#xff0c;副总裁和高桥名人去查看角色和游戏的开发情况&#xff0c;当他们查看正在构建的角色时&am…

C++类和对象的基础介绍(1)

类的定义 C类的关键字是class&#xff0c;学过c的朋友们可能会觉得和结构体struct有点像。 在C中struct也可以定义类&#xff0c;但和class定义的有所区别。 我们还是推荐使用class。 类里面会有成员变量、成员函数的定义和声明、构造函数、拷贝构造函数、析构函数、运算符…

迈巴赫S480升级大柏林音响31个喇叭8个座椅震动加上后排按摩座椅更加舒适

迈巴赫 S480 改装大柏林音响的改装案例&#xff1a; 改装前的车辆音响系统&#xff1a; 迈巴赫 S480 原车配备了 15 个喇叭的小柏林音响系统。 改装方案&#xff1a; 1. 扬声器升级&#xff1a;将原车的小柏林音响全部拆下&#xff0c;更换为大柏林的扬声器。大柏林音响系统…

SCMsafe链四方参展2024第三届医药供应链创新大会

024年8月22日-24日&#xff0c;由智慧医药主办&#xff0c;多家行业协会、研究机构、生产、流通及供应链公司协办的2024第三届医药供应链创新大会在杭州召开。 会议以“正在遇见的革命”为主题&#xff0c;聚焦生产、流通及终端医药供应链热点、痛点政策和市场话题&#xff0c;…

opencv实战项目十五:钢材表面缺陷检测

文章目录 前言一、算法实现流程&#xff1a;二&#xff0c;算法详解&#xff1a;2.1 二值化与去噪2.2 形态学处理 三&#xff0c;整体代码实现&#xff1a; 前言 随着科技的不断进步&#xff0c;自动化和智能化在工业生产中的应用越来越广泛。在钢材生产过程中&#xff0c;钢材…

认知杂谈33

今天分享 有人说的一段争议性的话 I I 《说话影响命运&#xff0c;得小心》 嘿&#xff0c;你想想看&#xff0c;咱平常不经意说的那些话&#xff0c;就像小种子一样。你可能没当回事&#xff0c;可说不定啥时候&#xff0c;这些话就会在生活里生根发芽&#xff0c;最后生活…

继承—构造函数—引用等

继承时&#xff0c;数据成员&#xff0c;函数成员全盘接收&#xff0c;如果碰见同名成员屏蔽基类成员。 1&#xff0c;无论采取什么继承方式&#xff0c;基类中所有数据成员都将继承到派生类 2&#xff0c;在类型的继承层次里&#xff0c;保护属性当作共有属性使用 3&#x…

Xv6驱动(一):PLIC

PLIC内存布局 #define PLIC 0x0c000000L #define PLIC_PRIORITY (PLIC 0x0) #define PLIC_PENDING (PLIC 0x1000) #define PLIC_SENABLE(hart) (PLIC 0x2080 (hart) * 0x100) #define PLIC_SPRIORITY(hart) (PLIC 0x201000 (hart) * 0x2000) #define PLIC_SCLAIM(hart) …

前端算法 ==== 栈的好戏还要继续!| 1047. 删除字符串中的所有相邻重复项

目录 解题 思路 题外话 给出由小写字母组成的字符串 S&#xff0c;重复项删除操作会选择两个相邻且相同的字母&#xff0c;并删除它们。 在 S 上反复执行重复项删除操作&#xff0c;直到无法继续删除。 在完成所有重复项删除操作后返回最终的字符串。答案保证唯一。 输入&a…

E-Prime2中同时识别大小写字母与中文支持设置

识别大小写 起因是在学习Eprime过程中发现&#xff0c;一开始只设置了键盘反应为q&#xff0c;然后当键盘为大写状态时&#xff0c;按Q不会响应&#xff0c;后来看到可以同时设置Qq&#xff0c;并且也能读取&#xff0c;简单试了一下&#xff0c;发现有必要在其他地方也这么设…

Multi-class Token Transformer for Weakly Supervised Semantic Segmentation

code&#xff1a;https://github.com/xulianuwa/MCTformer 摘要 本文提出了一种基于Transformer的新框架&#xff0c;用于学习类别特定的对象定位图&#xff0c;并将其作为弱监督语义分割&#xff08;WSSS&#xff09;的伪标签。受到标准视觉Transformer中单类别token的关注区…

SpringBoot天猫商城基于前后端分离+SpringBoot+BootStrap、Vue.js、JQuery+JPA+Redis

SpringBoot天猫商城整站 一、项目介绍和演示 SPRINGBOOT天猫整站&#xff0c;基于 前后端分离思想&#xff0c; 由于该商城高并发的特点&#xff0c;后端框架便使用了方便维护的 SpringM VC、SpringBoot框架&#xff0c;而前端框架则选择了主流的BootStrap、Vue.js&#xff0c;…