第4章主要介绍如何构造线程安全类。

在设计线程安全类的过程中,需要包含以下三个基本要素:

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

构造线程安全类常采用的技术如下:

  • 实例封闭

当一个对象被封装到另一个对象中时,能够访问被封装对象的所有代码路径都是已知的。与对象可以由整个程序访问的情况相比,更易于对代码进行分析。通过将封闭机  制与合适的加锁策略结合起来,可以确保以线程安全的方式来使用非线程安全的对象。

对象一般可以封闭在三种地方:

  1. 封闭在类的一个实例中,例如作为类的一个私有成员。
  2. 封闭在某个作用域内,例如作为一个局部变量。
  3. 封闭在线程内,例如在某个线程中将对象从一个方法传递到另一个方法,而不是在多个线程之间共享该对象。

在Java平台的类库中有很多线程封闭的示例,比如一些基本的容器类并非线程安全的,例如ArrayList和HashMap,但类库提供了包装器工厂方法,使得这些非线程安全的类可以在多线程环境中安全地使用。

  • 委托

如果一个类是由多个独立且线程安全的状态变量组成,并且在所有的操作中都不包含无效状态转换,那么可以将线程安全性委托给底层的状态变量。

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

例子:假设需要一个线程安全的链表,它需要提供一个原子的“若没有则添加(put-if-Absent)”的操作

1.扩展

 public class BetterVector<E> extends Vector<E> {
public synchronized boolean putIfAbsent(E x) {
boolean absent = !contains(x);
if (absent) {
add(x);
}
return absent;
}
}

这种方法的缺点是:导致了现在的同步策略实现被分布到多个单独维护的源代码文件中,一旦底层的类改变了同步策略并选择了不同的锁来保护它的状态变量,那么子类会被破坏,因为在同步策略改变后无法再使用正确的锁来控制对基类状态的并发访问。

2.客户端加锁机制

 public class ListHelper<E> {

     public List<E> list = Collections.synchronizedList(new ArrayList<E>());
...
public boolean putIfAbsent(E x) {
synchronized (list) {
boolean absent = !list.contains(x);
if (absent) {
list.add(x);
}
return absent;
}
} }

这种方式很脆弱,因为它将类C的加锁代码放到与C完全无关的其他类中,会导致混乱的。

客户端加锁机制与扩展类机制的共同点:将派生类的行为与基类的实现耦合在一起,扩展破坏了实现的封装性,客户端加锁破坏了同步策略的封装性。

3.组合

 public class ImprovedList<E> implements List<E> {

     private final List<E> list;

     public ImprovedList(List<E> list) {
this.list = list;
} public synchronized boolean putIfAbsent(E x) {
boolean contains = list.contains(x);
if (contains) {
list.add(x);
}
return !contains;
} public synchronized void clear() {
list.clear();
}
//....按照类似的方式委托List的其他方法
}

这里其实使用了Java监视器模式来封装现有的List,并且只要在类中拥有指向底层List的唯一外部引用,就能确保线程安全性。

最后需要将同步策略文档化。

Java并发编程实战4章的更多相关文章

  1. JAVA并发编程实战---第二章:线程安全性

    对象的状态是指存储在状态变量中的数据.对象的状态可能包括其他依赖对象的域.例如HashMap的状态不仅存储在HashMap本身,还存储在许多Map.Entry对象中.对象的状态中包含了任何可能影响其外 ...

  2. Java并发编程实战3章

    1.同步包括两方面:原子性和可见性. 2.可见性:因为在多线程程序中,如果没有采用正确的同步,有些线程就会得到失效数据. Java内存模型要求,变量的读取操作和写入操作都必须是原子操作,但对于非vol ...

  3. Java并发编程实战---第六章:任务执行

    废话开篇 今天开始学习Java并发编程实战,很多大牛都推荐,所以为了能在并发编程的道路上留下点书本上的知识,所以也就有了这篇博文.今天主要学习的是任务执行章节,主要讲了任务执行定义.Executor. ...

  4. 《Java并发编程实战》/童云兰译【PDF】下载

    <Java并发编程实战>/童云兰译[PDF]下载链接: https://u253469.pipipan.com/fs/253469-230062521 内容简介 本书深入浅出地介绍了Jav ...

  5. 《java并发编程实战》笔记

    <java并发编程实战>这本书配合并发编程网中的并发系列文章一起看,效果会好很多. 并发系列的文章链接为:  Java并发性和多线程介绍目录 建议: <java并发编程实战>第 ...

  6. Java并发编程实战 03互斥锁 解决原子性问题

    文章系列 Java并发编程实战 01并发编程的Bug源头 Java并发编程实战 02Java如何解决可见性和有序性问题 摘要 在上一篇文章02Java如何解决可见性和有序性问题当中,我们解决了可见性和 ...

  7. Java并发编程实战 04死锁了怎么办?

    Java并发编程文章系列 Java并发编程实战 01并发编程的Bug源头 Java并发编程实战 02Java如何解决可见性和有序性问题 Java并发编程实战 03互斥锁 解决原子性问题 前提 在第三篇 ...

  8. Java并发编程实战 05等待-通知机制和活跃性问题

    Java并发编程系列 Java并发编程实战 01并发编程的Bug源头 Java并发编程实战 02Java如何解决可见性和有序性问题 Java并发编程实战 03互斥锁 解决原子性问题 Java并发编程实 ...

  9. Java并发编程实战——读后感

    未完待续. 阅读帮助 本文运用<如何阅读一本书>的学习方法进行学习. P15 表示对于书的第15页. Java并发编程实战简称为并发书或者该书之类的. 熟能生巧,不断地去理解,就像欣赏一部 ...

随机推荐

  1. 010杰信-创建购销合同Excel报表系列-3-新增合同货物:这里涉及到子表的新增(合同货物表是购销合同表的子表)

    效果说明: 前面分析过购销合同的Excel报表需要四张表,这篇讲的是合同货物表. 这个合同货物表是购销合同的子表,是一个购销合同有多个合同货物的关系.在合同货物表中有购销合同的主键作为外键.所以这张表 ...

  2. 第二百八十一节,MySQL数据库-SQL注入和pymysql模块防止SQL注入

    MySQL数据库-SQL注入和pymysql模块防止SQL注入 SQL注入就是通过SQL语句绕开程序判断,获取到数据库的内容 下面以一个简单的程序登录SQL注入举例: 正常登录 1.数据库有一张会员表 ...

  3. java 多线程 1 “常用的实现多线程的2种方式”:Thread 和 Runnable

    转载系列自http://www.cnblogs.com/skywang12345/p/java_threads_category.html 当使用第一种方式(继承Thread的方式)来生成线程对象时, ...

  4. hdu 1026:Ignatius and the Princess I(优先队列 + bfs广搜。ps:广搜AC,深搜超时,求助攻!)

    Ignatius and the Princess I Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (J ...

  5. Objective-C 成员变量

    成员变量的访问权限 Objective-C中的成员变量有以下三种属性 public(外部及其子类可访问) protected(子类可访问,外部不可访问) private(外部及其子类不可访问) 默认情 ...

  6. C# 直接调用非托管代码的方法

    C# 代码有以下两种可以直接调用非托管代码的方法: 直接调用从 DLL 导出的函数. 调用 COM 对象上的接口方法. 对于这两种技术,都必须向 C# 编译器提供非托管函数的声明,并且还可能需要向 C ...

  7. Angular 表单(二) - 模板驱动表单

    import { Component, OnInit } from '@angular/core'; import { Hero} from '../hero'; @Component({ selec ...

  8. __name__

    __name__ 是 python 的一个内置变量,它的值等于 '__main__' ,如下: [root@localhost ~]$ cat talk.py #!/usr/bin/env pytho ...

  9. tomcat 权限问题

    http://blog.csdn.net/testcs_dn/article/details/39252433 chmod -R 755 apache-tomcat-7.0.63 pwd :mac 看 ...

  10. 微软向开源又迈进了一大步:Checked C

    导读 微软开源了 Checked C ,这是一个 C 语言的扩展版本,可以用于解决 C 语言中的一系列安全相关的隐患.正如其名字所示,Checked C 为 C 语言增加了检查,这个检查可以帮助开发者 ...