《代码整洁之道》--第13章 并发

1. 为什么要并发
  a) 并发是一种解耦策略。他帮助我们吧做什么(目的)和何时做(时机)分解开。
  b) 在web应用的servlet模式下,当有web请求时,servlet就会异步执行。
2. 挑战
  a) 当两个线程相互影响时就会出现不可预期的情况。这是因为线程在执行那行java代码时有许多可能路径可行,有些路径会产生错误的结果。回答这个问题需要理解 Just-IN-Time编译器如何对待生成的字节码,还

  要理解java内存模型认为什么东西具有原子性
3. 并发防御原则
  a) SRP
    i. 并发相关的代码有自己的开发,修改和调优生命周期
    ii. 开发相关代码有自己要对付的挑战,和非并发代码不同
    iii. 即便没有周边应用程序增加的负担,写的不好的并发代码可能的出错方式数量也足够挑战性
    iv. 建议:分离并发代码和其他代码
  b) 推论:限制数据作用域
    i. 谨记数据封装;严格限制对可能被共享的数据的访问
  c) 推论:使用数据复本
    i. 从一开始就避免共享数据,从多线程收集所有副本的结果,并在单个线程中合并这些结果
  d) 推论:线程应尽可能地独立
    i. 尝试将数据分解到可被独立线程(可能在不同处理器上)操作的独立子集
4. 了解java库
  a) 线程安全群集
    i. Java.util.concurrent,    java.util.concurrent.atomic         java.util.concurrent.locks
5. 了解执行模型
  a)

  

  b) 生产者-消费者模型
  c) 读者-作者模型 (吞吐量和正常操作)
  d) 宴席哲学家
6. 警惕同步方法之间的依赖
  

7. 保持同步区域微小
8. 很难编写正确的关闭代码
  a) 考虑正常关闭问题
9. 测试线程代码
  a) 不要将系统错误归咎于偶发事件
  b) 不要追踪非线程缺陷和线程缺陷。确保代码可以在线程之外工作
  c) 编写可插拔的线程代码,这样就能在不同的配置环境运行

 

 


附录:
A1:客户端/服务器段例子
  

 

 

  对于并发编程,因其复杂性,应该将全部代码,根据SRP,放到少数类中。

 

A2:可能执行的路径
    

 

     

 

 

    


    理解线程之间如何相互干涉,并不一定要精通字节码文件,只需要知道多个线程之间互相干涉的可能性。
    有必要理解内存模型,明白什么是安全的,什么是不安全的。
    必须知道什么地方有共享对象/值;哪些代码会导致并发读/写的问题;如何防止这种并发问题发生。

 

A3: 了解类库

   

 

 

  3.2:非锁定的解决方案:

    原子类。
    CAS(compare and swap )机制,类似于数据库中的乐观锁定,而其同步版本类似于保守锁定。

    

 

   3.3非线程安全类:

    数据库连接、java.util容器、servlet


A4:方法之间的依赖可能破坏并发代码

  

 

   

  多线程调用的时候,hasnext()的地方可能击穿
  

  解决的方法:
    容忍错误: 相当于电脑坏了重启电脑,并不能解决问题
    基于客户端代码的锁定: 不可靠
    基于服务端的修改:
      

    可以使用下述方法不改变客户端接口:
      

 

 

A5:提升吞吐量
  

 

   

 

 


 

posted @ 2019-09-26 16:38  _Meditation  阅读(240)  评论(0编辑  收藏  举报