美文网首页
Java并发编程实战

Java并发编程实战

作者: 海边的贝壳林 | 来源:发表于2017-10-05 17:22 被阅读0次

竞态条件


第四章 对象的组合

通过各种组合模式让一个类是线程安全的.

设计线程安全的类

步骤:

  1. 找出构成对象状态的所有变量.
  2. 找出约束变量状态的"不变性条件".
  3. 建立对象状态的并发访问管理策略.

原子性和封装性来保证线程安全.

  • 如果需要在状态的变换过程中添加条件约束(先检查后执行), 那么就需要利用到原子性和封装性来保证线程安全. 避免检查之后的状态变量被其他线程更改.
  • 为了保证有效值, 如更新小汽车的位置x, y时, 更新x,y时必须是原子的, 不然可能会导致出现更新了x之后更新y时, x被其他线程更改了的情况发生.

状态所有权

类对其所封装的状态拥有所有权. 对其发布的状态最多拥有共享控制权, 大多从构造函数和方法中传递进来的对象, 类通常不拥有这些对象.

容器类的 "所有权分离"

容器类拥有其自身状态的控制权, 而客户代码才拥有容器中的各个对象的状态. 如ServletContext, 其拥有类似的map的上下文容器对象, 但是并不拥有ServletContext中的包含的对象, 要安全的使用存储在ServletContext中的对象, 必须保证下面其中之一的条件: 对象是线程安全的, 对象是事实不可变的, 对象是由锁保护的.

通过 实例封闭 的形式保证线程安全.

将状态数据封装在对象内部. 对所有访问该对象的路径都进行线程安全的策略配置. 对象的状态完全由其内置锁来保护.

私有锁

私有的锁对象可以将锁封装起来, 客户代码无法获得到锁.

线程的委托

将对象的线程安全委托给一个或多个线程安全的不可变对象. 若是委托给多个对象, 则要求这多个对象之间是没有关系的, 如果有联系, 则需要锁来同步操作.

在现有的线程安全类中添加功能.

比如添加一个'如果不存在就添加'的功能. 肯定是要先检查, 再执行的, 为了保证线程安全, 这两步必须是原子的. 那么如何实现呢.

  1. 修改原始类: 基本很难实现, 因为原始类有可能在jar包中或者有其他原因不能更改.
  2. 扩展原始类: 方式并不是很牢靠, 因为要求原始类的状态对子类是开放的, 日后基类的同不策略发生变化可能会影响到子类的, 类的功能维护在了子类中.
  3. 客户端加锁: 要使用这个方法对某个X对象加锁, 则必须知道X对象使用了什么锁. 2和3都破坏了封装性
  4. 组合: 例如对某个List对象X进行添加功能, 则将X赋值给组合类的内部List引用, 组合类采用自身的内置锁增加了额外一层的锁. 这种模式更加健壮.

相关文章

网友评论

      本文标题:Java并发编程实战

      本文链接:https://www.haomeiwen.com/subject/jexkyxtx.html