clean code-代码整洁之道 阅读笔记(第十三章)

第十三章 并发编程

"对象是过程的抽象。线程是调度的抽象。"

--James O Coplien

13.1 为什么要并发 

        并发是一种解耦策略。它帮助我们把做什么(目的)和何时(时机)做分解开。在单线
程应用中,目的与时机紧密耦合,很多时候只要查看堆栈追路即可断定应用程序的状态。

        解耦目的与时机能明显地改进应用程序的吞吐量和结构。从结构的角度来看,应用程序看起来更像是许多台协同工作的计算机,而不是一个大循环。系统因此会更易于被理解,给出了许多切分关注面的有力手段。

迷思与误解
  1. 并发总能改进性能
  2. 编写并发程序无需修改设计
  3. 在采用Web或EJB容器的时候,理解并发问题并不重要

中肯说法

  1. 并发会在性能和编写额外代码上增加一些开销
  2. 正确的并发是复杂的,即便对于简单的问题也是如此;
  3. 并发缺陷并非总能重现,所以常被看做偶发事件而忽略,未被当做真正的缺陷看待;
  4. 并发常常需要对设计策略的根本性修改
13.2 挑战
public class X{private int lastIdUsed;public int getNextId(){return ++lastIdUsed;}
}

比如,创建x的一个实体,将lastIdUsed设置为42,在两个线程中共享这个实体。假设这两个线程都调用getNextId()方法,结果可能有三种输出:

  • 线程一得到值43,线程二得到值44,lastIdUsed为44;
  • 线程一得到值44,线程二得到值43,lastIdUsed为44;
  • 线程一得到值43,线程二得到值43,lastIdUsed为43。

        就生成的字节码而言,对于在getNextId方法中执行的那两个线程,有12870种不同的可能执行路径。如果lastIdUsed的类型从int变为long,则可能路径的数量将增至2704156种。当然,多数路径都得到正确结果。问题是其中一些不能得到正确结果。

13.3 并发防御原则
13.3.1 单一权责原则

问题:

  • 并发相关代码有自己的开发、修改和调优生命周期;
  • 开发相关代码有自己要对付的挑战,和非并发相关代码不同,而且往往更为困难;
  • 即便没有周边应用程序增加的负担,写得不好的并发代码可能的出错方式数量也已经足具挑战性。

建议:分离并发相关代码与其他代码。

13.3.2 推论:限制数据作用域

        两个线程修改共享对象的同一字段时,可能互相干扰,导致未预期的行为。解决方案之一是采用synchronized关键字在代码中保护一块使用共享对象的临界区(criticalsection)。

可能出现的问题:

  1. 你会忘记保护一个或多个临界区——破坏了修改共享数据的代码码;
  2. 得多花力气保证一切都受到有效防护(破坏了DRY原则);
  3. 很难找到错误源,也很难判断错误源。

建议:谨记数据封装;严格限制对可能被共享的数据的访问。

13.3.3 推论:使用数据复本

        避免共享数据的好方法之一就是一开始就避免共享数据。在某些情形下,有可能复制对象并以只读方式对待。在另外的情况下,有可能复制对象,从多个个线程收集所有复本的结果,并在单个线程中合并这些结果。

13.3.4 推论:线程应尽可能地独立

        让每个线程在自己的世界中存在,不与其他线程共享数据。每个线程处理一个客户端请求,从不共享的源头接纳所有请求数据,存储为本地变量。这样一来,每个线程都像是世界中的唯一线程,没有同步需要。

建议:尝试将数据分解到可被独立线程(可能在不同处理器上)操作的独立子集。

13.4 了解Java库
  • 使用类库提供的线程安全群集;
  • 使用executor框架(executorframework)执行无关任务;
  • 尽可能使用非锁定解决方案;
  • 有几个类并不是线程安全的。
13.5 了解执行模型

13.5.1 生产者-消费者模型

        生产者和消费者之间的队列是一种限定资源。

13.5.2 读者-作者模型

        当存在一个主要为读者线程提供信息源,但只偶尔被作者线程更更新的共享资源,吞吐量就会是个问题。增加吞吐量,会导致线程饥饿和过时信息的累积。更新会影响吞吐量。

        挑战之处在于平衡读者线程和作者线程的需求,实现正确操作,提供合理的吞吐量,避免线程饥饿。

13.5.3 宴席哲学家

        如果没有用心设计,这种竞争式系统就会遭遇死锁、活锁、吞吐量和效率降低等问题。

可能遇到的并发问题,大多数都是这三个问题的变种。

建议:学习这些基础算法,理解其解决方案。

13.6 警惕同步方法之间的依赖

        建议:避免使用一个共享对象的多个方法。

必须使用一个共享对象的多个方法的3种手段:

  1. 基于客户端的锁定——客户端代码在调用第一个方法前锁定服务端,确保锁的范围覆盖了调用最后一个方法的代码;
  2. 基于服务端的锁定——在服务端内创建锁定服务端的方法,调用所有方法,然后解锁。让客户端代码调用新方法;
  3. 适配服务端——创建执行锁定的中间层。这是一种基于服务端的的锁定的例子,但不修改原始服务端代码。
13.7 保持同步区域微小

        关键字synchronized制造了锁。锁是昂贵的,因为它们带来了延迟和额外开销。

        另一方面,临界区应该被保护起来。所以,应该尽可能少地设计临界区。

        将同步延展到最小临界区范围之外,会增加资源争用、降低执行效率。

13.8 很难编写正确的关闭代码

        平静关闭很难做到。常见问题与死锁有关,线程一直等待永远不会到来的信号。

        建议:尽早考虑关闭问题,尽早令其工作正常。这会花费比你预期更多的时间。检视既有算法,因为这可能会比想象中难得多。

13.9 测试线程代码

        建议:编写有潜力曝露问题的测试,在不同的编程配置、系统配置和负载条件下频繁运行。如果测试失败,跟踪错误。别因为后来测试通过了后来的运行就忽略失败。

  • 将伪失败看作可能的线程问题 => 不要将系统错误归咎于偶发事件
  • 先使非线程代码可工作 => 不要同时追踪非线程缺陷和线程缺陷。
  • 编写可插拔的线程代码
  • 编写可调整的线程代码
  • 运行多于处理器数量的线程
  • 在不同平台上运行
  • 调整代码并强迫错误发生。
13.10 小结

        第一要诀是遵循单一权责原则。

        了解并发问题的可能原因。

        学习类库,了解基本算法。

        学习如何找到必须锁定的代码区域并锁定之。不要锁定不必针锁定的代码。

        要能在不同平台上、以不同配置持续重复运行线程代码。

       如果花点时间装置代码,就能极大地提升发现错误代码的机会。

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

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

相关文章

【OpenCV 图像处理 Python版】OpenCV 简介及安装

文章目录 1.OpenCV 介绍1.1 OpenCV 的特点1.2 OpenCV 的主要模块1.3 OpenCV 的应用场景 2.OpenCV-Python 库3.OpenCV 安装 1.OpenCV 介绍 OpenCV(Open Source Computer Vision Library)是一个开源的计算机视觉和机器学习软件库。它由英特尔公司于1999年…

API的优势及应用场景(淘宝API测试的详细步骤)

一、API的优势 API的出现为应用程序间的通信提供了一种新的方式,它有以下优势: 1、降低开发难度 开发者可以通过API访问其他应用程序的数据和功能,避免了重复开发,降低了开发难度。 2、提高开发效率 API提供了一种标准化的通…

使用AES,前端加密,后端解密,spring工具类,直接c就完事了

学习python的时候,看到很多会对参数进行加密,于是好奇心驱使下,让我去了解了下AES加密如何在java中实现。 首先 npm install crypto-js 然后在你的方法中,给你们前端源码看看,因为我用的ruoyi框架做的实验&#xff…

构建一个检索增强生成(RAG)应用程序

:::tips 此文档是LangChain官方教程的实践总结:https://python.langchain.com/v0.2/docs/tutorials/rag/实践前你需要准备:OPENAI_API_KEY Generator:根据检索到的信息和用户的查询生成自然语言的回答。LANGCHAIN_API_KEY 密切监控和评估您的…

【自然语言处理系列】掌握NLP基础:去停用词、词性标注与命名实体识别实战教程

摘要:本系列教程专注于自然语言处理(NLP)中的基础元素,包括去停用词、词性标注以及命名实体识别。这些步骤是文本预处理和分析不可或缺的组成部分。我们将通过具体的实例和技术演示,讲解如何使用Python及其相关库&…

网络安全之Windows提权(上篇)(高级进阶)

目录 一,什么是提权? 二,提权的前提 三,如何提权? 1,第一步连接服务器 2,提升权限至iuser​编辑 3,利用补丁漏洞提权至最高级 四,总结 一,什么是提权&am…

大数据集群数据传输

简单的服务器间的通信示例 netcat,简写为 nc,是 unix 系统下一个强大的命令行网络通信工具,用于在两台主机之间建立 TCP 或者 UDP 连接,并提供丰富的命令进行数据通信。nc 在网络参考模型属于应用层。使用 nc 可以做很多事情&…

重磅丨上海容大推出“容聆”智能拾音工牌,赋能线下门店运营数字化

近日,继豚音营业厅智能质检终端之后,上海容大数字技术有限公司(简称“上海容大”)在线下面对面沟通场景下语音数据采集与智能分析领域取得了新突破,重磅推出AI智能语音工牌产品——“容聆”。 据悉,“容聆”…

mybatis x插件的使用教程(详细)

MyBatisX 的主要功能 代码生成: 自动生成 MyBatis 的 Mapper、XML 配置文件和实体类,大大减少手工编写代码的工作量。 智能代码补全: 提供 SQL 语句和 MyBatis 配置的智能代码补全功能,使开发者能够更快地编写代码。 代码导航&…

铀的危害和应用,以及铀的分离提纯

铀是一种锕系放射性元素,对人体存在一定的危害,如辐射损伤、呼吸系统损伤、神经系统损伤、免疫系统损伤等。 1、辐射损伤:铀的放射性会对人体产生辐射损伤,长期接触会增加患癌症的风险。此外,还可能对人体正常细胞产生…

【网络安全的神秘世界】解决dvwa靶场报错:Illegal mix of collations for operation ‘UNION‘

🌝博客主页:泥菩萨 💖专栏:Linux探索之旅 | 网络安全的神秘世界 | 专接本 | 每天学会一个渗透测试工具 🚩问题描述 当尝试执行如下 SQL 语句时: 1 union select schema_name,1 from information_schema.s…

如何挑选护眼灯?一分钟带你了解挑选护眼灯的六大准则!

小时候,对正确用眼知识一无所知,也不明白何种光线环境对眼睛最为友善,结果如今的近视度数已濒临千度大关。虽然早已习惯佩戴眼镜的生活,但近视所带来的诸多不便仍旧在日常生活中无处不在。因此,对于家中孩子的视力健康…

第六十七:iview的select组件在页面上,下拉数据被遮挡

iview的select组件在页面上,下拉数据被遮挡 加上**:transfer"true"** 代码截图: 官方解说截图:因为默认值是false 所以要改成:transfer“true”

人工智能水平国际领先,科大讯飞再获国家科学技术进步奖一等奖

科大讯飞在2023年6月24日荣获国家科学技术进步奖一等奖,这是对其在多语种智能语音技术及产业化领域取得的突破性成果的高度认可。科大讯飞的这一成就,标志着其在人工智能领域的技术实力和创新能力已达到国际领先水平。 据「TMT星球」了解,科大…

WMV 视频格式怎么转换?WMV 视频为什么不流行了?

目前有越来越多的视频格式类型,如常见的 MP4、FLV、AVI 等等,而技术的演变也逐渐让一些常见的视频格式变的越来越少了。 今天我们一起来聊下 WMV 这个视频格式,让我们看看它的发展以及为什么现在越来越少人使用了。 什么是 WMV 视频格式&…

Git 使用指南(附详细解释)

Git 是一个强大的版本控制系统,广泛用于软件开发中,用于跟踪文件的更改、协作工作等。无论你是新手还是有经验的开发者,掌握 Git 都是非常有益的。这篇博客将带你了解 Git 的基本使用,希望能帮助你快速入门并有效使用 Git。 1. 创…

【windows|011】TCP/IP5层模型常见协议及应用总结大全

🍁博主简介: 🏅云计算领域优质创作者 🏅2022年CSDN新星计划python赛道第一名 🏅2022年CSDN原力计划优质作者 ​ 🏅阿里云ACE认证高级工程师 ​ 🏅阿里云开发者社区专家博主 💊交流社…

java设计模式(二)工厂方法模式(pattern of factory method)

1、模式介绍: 工厂方法模式(pattern of factory method)是一种创建型设计模式,它定义了一个用于创建对象的接口,但将实际创建对象的工作延迟到子类中,这样可以在不改变整体结构的情况下,通过子…

第二节课 6月13日 ssh密钥登陆方式

centos和ubuntu openssh服务的初始安装 一、实验:ubuntu系统激活root用户 ubuntu系统如何激活root用户,允许root用户ssh登陆? 1、ubuntu默认root用户未设置密码,未激活 激活root用户,设置root密码 sudo passwd roo…

vray灯光导致3dmax崩溃怎么解决?

启动时崩溃 解决方法: 1、兼容模式重新打开 具体步骤:【选中会闪退3dmax版本】——【右键“兼容性疑难解答”】——【下一步】——【选择Windows7/10】——【下一步】——【启动程序】 启动完成后,【下一步】——【为我保存这些设置】—完…