为什么要并发
并发是一种解耦策略。它帮助我们把做什么(目的)和何时(时机)做分解开。解耦目的与时机能明显地改进应用程序的吞吐量和结构。
迷思和误解
1、并发总能改进性能:并发只在多个线程或处理器之间能分享大量等待时间的时候才能改进性能。
2、编写并发程序无需修改设计:并发算法的设计有可能与单线程系统的设计极不相同。目的与时机的解耦往往对系统结构产生巨大影响。
3、在采用容器的时候,理解并发问题并不重要:了解容器在做什么才能对付并发更新、死锁等问题。
编写并发软件的中肯说法
1、并发会在性能和编写额外代码上增加一些开销。
2、正确的并发是复杂的,即便对于简单的问题也是如此。
3、并发缺陷并非总能重现,所以常被看做偶发事件而忽略,未被当做真的缺陷看待。
4、并发常常需要对设计策略的根本性修改。
并发防御原则
1、单一权责原则。分离并发相关代码与其他代码。
2、限制数据作用域。谨记数据封装;严格限制对可能被共享的数据的访问。
3、使用数据复本。
4、线程应尽可能地独立。尝试将数据分解到可被独立线程(可能在不同处理器上)操作的独立子集。
了解执行模型
1、生产者-消费者模型。生产者和消费者之间的队列是一种限定资源。
2、读者-作者模型。平衡读者线程和作者线程的需求,提供合理的吞吐量,避免线程饥饿。
3、宴席哲学家。学习基础算法,理解其解决方案。
警惕同步方法之间的依赖
避免使用一个共享对象的多个方法。如果必须使用时有3种写对代码的手段:
1、基于客户端的锁定
2、基于服务端的锁定
3、适配服务端
保持同步区域微小
尽可能减小同步区域
很难编写正确的关闭代码
尽早考虑关闭问题,尽早令其工作正常。这会花费比你预期更多的时间。检视既有算法,因为这可能会比想像中难得多。
测试线程代码
编写有潜力曝露问题的测试,在不同的编程配置、系统配置和负载条件下频繁运行。如果测试失败,跟踪错误。别因为后来测试通过了后来的运行就忽略失败。
测试线程代码时的一些精练的建议:
1、将伪失败看作可能的线程问题。 不要将系统错误归咎于偶发事件。
2、先使非线程代码可工作。不要同时追踪非线程缺陷和线程缺陷。确保代码在线程之外可工作。
3、编写可插拔的线程代码。 编写可插拔的线程代码,这样就能在不同的配置环境下运行。
4、编写可调整的线程代码。 在系统运行是允许线程发生变动。允许线程依据吞时量和系统使用率自我调整。
5、运行多于处理数量的线程。 运行多于处理器或处理器核心数量的线程。任务交换越频繁,越有可能找到错过临界区或导致死锁的代码。
6、在不同平台上运行。 尽早并经常地在所有目标平台上运行线程代码。
7、装置试错代码
硬编码:改变代码的执行路径,制造错误。
自动化:使用异动策略搜出错误。