并发编程
为什么要并发
- 并发是一种解耦策略,他帮助我们什么和何时做分解开
迷思和误解
- 并发在性能和编码上增加一些开销
- 正确的并发是复杂的
- 并发缺陷并非总能重现,所以常被看做偶发事件而忽略
- 并发常常需要对设计策略的根本性做改变
并发是一个挑战
并发防御原则
单一权责(SRP)
- 并发相关代码有自己的开发、修改、和调优生命周期
- 开发相关代码自己要对付的挑战,和并发相关代码不同
- 分析并发相关代码和其他代码
限制数据作用域(采用synchronized关键字保护代码中使用的共享对象的临界区域)
- 谨记数据封装,严格限制对可能被数据共享的数据的访问
使用数据副本
- 避免共享数据的好方法之一就是一开始就避免共享数据
- 能避免数据共享就避免,代码会减少很多错误的可能性
线程尽可能独立
- 让每个线程在自己的世界中存在,不与其他线程共享数据
- 尝试将数据分解到可被独立的线程
了解java库
了解执行模型
生产者-消费者模型
- 生产者和消费者之间的队列是一种限定资源
读者-作者模型
- 当存在一个主要为读者线程提供信息员,但是只是偶尔被作者线程更新的共享资源,吞吐量是个问题。增加吞吐量,导致饥饿和过时信息的积累。更新会议向吞吐量,这是一种平衡工作,会很辛苦
宴席哲学家
- 线程代替哲学家,资源代表叉子。如果没有用心设计,这种情况有可能会在哦成死锁,活锁,吞吐量等问题
- 学习这些算法解决其解决的方案
警惕同步方法的依赖
- 避免使用一个共享对象的多个方法
有时必须使用一个共享对象的多个方法,这种情况发生时,有3种手段解决
- 基于客户端锁定:客户端在调用第一个方法前锁定服务端,确保锁的范围覆盖最后一个方法
- 基于服务端锁定:服务端创建锁定服务端的方法,调用所有方法,然后解锁,让客户端调用新方法
- 适配服务端:创建执行锁定的中间层。这是基于服务端锁定的例子
保持同步区域微小
- 关键字synchronized制造了锁。同一个锁维护的所有代码区域在任一时刻保证只有一个线程执行,锁昂贵啊,临界区域是被保护起来的,应该尽量少使用
很难编写正确的关闭代码
- 尽早考虑关闭问题,尽早令其工作正常
测试线程代码
- 将伪失败看作可能的线程问题
- 先使非线程代码可工作
- 编写可插拔的线程代码
- 编写可调整的线程代码
- 运行多于处理器数量的线程
- 在不同平台上运行
- 调整代码并强迫错误发生
不要将系统错误归咎于偶发事件
先使肺线程代码工作
- 不要同时追踪线程缺陷和非线程缺陷
编写可插拔代码
- 单线程和多线程在执行时不同的情况
- 线程代码和实物或测试替身互动
- 用运行快速、缓慢和有变动的测试替身执行
- 将测试配置为能运行一定数量的迭代
编写可调整的线程代码
运行多于处理器数量的线程
在不同平台上运行
装置测试代码
- 硬编码
- 自动化