JAVA 并发编程—基础2

对象的组合

###1、设计线程安全的类   在设计线程安全类的过程中,需要包含以下三个基本要素 - 找出构成对象状态的所有变量。 - 找出约束状态变量的不变性条件。 - 建立对象状态的并发访问策略。

  要分析对象的状态,首先从对象的域开始。如果对象中所有的域都是基本类型的变量,那么这些类将构成对象的全部状态。
  同步策略定义了如何在不违背对象不变条件或后验条件的情况下对其状态的访问操作进行协同。同步策略规定了如何将不可变性、线程封闭与加锁机制等结合起来以维护线程的安全性。

###2、实例封闭
  如果对象不是线程安全的,可以通过多种技术使其在多线程程序中安全地使用。你可以确保对象只能由单个线程访问,或者通过一个锁保护对该对象的所有访问。
  封装简化了线程安全类的实现过程,它提供了一种实例封闭机制。将数据封装在对象内部,可以将数据的访问限制在对象的方法上,从而更容易确保线程在访问数据时总能持有正确的锁。

###3、线程安全性的委托
  可以将类的线程安全性委托给单个线程安全的状态变量。我们还可以将线程安全性委托给多个状态变量,只要这些变量是彼此独立的,即组合而成的类并不会在其包含的多个状态变量上增加任何不变性条件。
  如果一个状态变量是线程安全的,并且没有任何不变性条件来约束它的值,在变量的操作上也不存在任何不允许的状态转换,那么就可以安全地发布这个变量。
  

###4、在现有的线程安全类中添加功能
  当为现有的类添加一个原子操作时,有一个更好的办法:组合。

构建基础模块

###1、同步容器类
  这些同步的封装类是由Collections.synchronizedXxx等工厂方法创建的。

###2、并发容器
  同步容器将所有对容器状态的访问都串行化,以实现它们的线程安全性。这种方法的代价是严重降低并发性,当多个线程竞争容器的锁时,吞吐量将严重降低。
  ConcurrentHashMap也是一个基于散列的Map,但它使用了一种完全不同的加锁策略来提供更高的并发性和伸缩性。它在并发访问环境下将实现更高的吞吐量,而在单线程环境中只损失非常小的性能。它提供的迭代器不会抛出ConcurrentModificationException,因此不需要在迭代过程中对容器加锁。它返回的迭代器具有弱一致性。弱一致性的迭代器可以容忍并发的修改,当创建迭代器时会遍历已有的元素,并可以(但是不保证)在迭代器被构造后将修改操作反映给容器。尽管有这些改进,但仍然有一些需要权衡的因素。对于一些需要在整个Map上进行计算的方法,例如size和isEmpty,这些结果在计算时可能已经过期了。只有当应用程序需要加锁Map进行独占访问时,才应该放弃使用ConcurrentHashMap。
  CopyOnWriteArrayList在每次修改时,都会创建并重新发布一个新的容器副本,从而实现可变性。显然,每当修改容器时都会复制底层数组,这需要一定的开销,特别是当容器的规模较大时。仅当迭代操作远远多于修改操作时,才应该使用“写入时复制”容器。

###3、阻塞队列和生产者-消费者模式
  put方法的阻塞特性也极大地简化了生产者的编码。阻塞队列同样提供了一个offer方法,如果数据项不能被添加到队列中,那么将返回一个失败状态。这样就能创建更多灵活的策略来处理负荷过载的情况。在构建高可用的应用程序时,有界队列是一种强大的资源管理工具:它们能抑制并防止产生过多的工作项,是应用程序在负荷过载的情况下变得更加健壮。

###4、阻塞方法与中断方法
  线程可能会阻塞或暂停执行,原因有多种:等待I/O操作结束,等待获得一个锁,等待从Thread.sleep方法中醒来,或是等待另一个线程的计算结束。

###5、同步工具类
  CountDownLatch,FutureTask,Semaphore,CyclicBarrier

###6、构建高效且可伸缩的结果缓存
  

第一部分小结

  • 可变状态是至关重要的
      所有的并发问题都可以归结为如何协调对并发状态的访问。可变状态越少,就越容易保证现行安全
  • 尽量将域声明为final类型,除非需要它们是可变的。
  • 不可变对象一定是线程安全的
      不可变对象能极大地降低并发编程的复杂性。它们更为简单而且安全,可以任意共享而无须使用加锁或保护性复制等机制。
  • 封装有助于管理复杂性
      在编写线程安全的程序时,虽然可以将所有数据都保存在全局变量中,但为什么要这样做?将数据封装在对象中,更易于维持不变性条件;将同步机制封装在对象中,更易于遵循同步策略。
  • 用锁来保护每个可变变量
  • 当保护同一个不变性条件中的所有变量时,要使用同一个锁
  • 在执行复合操作期间,要持有锁
  • 如果从多个线程中访问同一个可变变量时没有同步机制,那么程序会出现问题
  • 不要故作聪明的推断出不需要使用同步
  • 在设计过程中考虑线程安全,或者在文档中明确地指出它不是线程安全的
  • 将同步策略文档化。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值