java并发编程实战-对象的组合

1,设计线程安全的类
  1.1,设计线程安全的类的过程中,需要包括以下三个基本要素:
    1.1.1,找出构成对象状态的所有变量
    1.1.2,找出约束状态变量的不变形条件
    1.1.3,建立对象状态的并发访问管理策略
  1.2,仅包含基本类型域的对象,其状态就是这些域构成的n元组;如果对象的域中引用了其他对象,那么该对象的状态还包括引用对象的域。
  1.3,同步策略规定了如何将不可变、线程封闭与加锁机制等结合起来以维护线程的安全性
  1.4,同步需求(后验条件):要满足在状态变量的有效值或者状态转换上的各种约束条件,就需要借助于原子性与封装性,如:对象中有两个变量min和max,要满足min<=max,那么对于min和max的更新或读取必须同时保证这两个变量必须在单个原子操作中进行
  1.5,依赖状态的操作(先验条件):如果某个操作包含有基于状态的先验条件,那么这个操作就称为依赖状态的操作。在单线程程序中,如果某个操作无法满足先验条件,那么就只能失败;但是在并发程序中要一直等到先验条件为真,然后再执行。Java中这种等待机制一般是通过阻塞队列(BlockingQueue)或者信号量(Semaphore)来实现
2,将数据封装在对象内部,可以将数据的访问限制在对象的方法上,从而更容易确保线程在访问数据时总能持有正确的锁
  2.1,对象可以封闭在类的一个实例中,或者封闭在某个作用域内,再或者封闭在线程内,例如在一个线程内从一个方法传递到另外一个方法,而不是在多个线程之间共享该对象
  2.2,遵循Java监视器模式的对象会把对象所有可变状态都封装起来,并由对象自己的内置锁来保护。Java监视器模式仅仅是一种编写代码的约定,对于任何一种锁对象,只要自始至终都是用该锁对象,都可以用来保护对象的状态
  2.3,使用私有的锁对象可以将锁封装起来,避免其他客户代码错误的获得该锁
  2.4,如果一个类由多个独立且线程安全的状态变量组成,并且在所有的操作中都不包含无效状态转换,那么可以将线程安全性委托给底层的状态变量。但是如果多个变量含有复合操作,这个类必须提供自己的加锁机制以保证这些复合操作的原子性

  2.5,如果一个状态变量是线程安全的,并且没有任何不变性条件来约束他的值,在变量操作上也不存在任何不允许的状态转换,那么就可以安全地发布这个变量,

3,为现有类添加原子操作
  3.1,客户端加锁:指的是:对于使用某个对象X的客户端代码,使用X本身用于保护其状态的锁来保护这段客户代码。客户端加锁很脆弱,因为它将类X的加锁代码放到与X无关的其他类中
    3.1.1,客户端加锁机制与扩展类机制有许多共同点,都是将派生类的行为与基类的实现耦合在一起,正如扩展会破坏封装性,客户端加锁同样会破坏同步策略的封装性
  3.2,组合:组合通过外部对象的自身加锁实现更加健壮的为现有类添加原子操作,它不关心被组合的底层类X是否实现了线程安全,或者即使类X的加锁方式改变了,外层类也会提供一致的加锁机制来实现线程的安全性,但是由于额外的同步层可能会导致轻微的性能损失
4,将同步策略文档化
  4.1,在文档中说明客户端代码需要了解的线程安全性保证,以及代码维护人员需要了解的同步策略

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值