Java并发编程实战4章
第4章主要介绍如何构造线程安全类。
在设计线程安全类的过程中,需要包含以下三个基本要素:
- 找出构成对象状态的所有变量。
- 找出约束状态变量的不变性条件。
- 建立对象状态的并发访问管理策略。
构造线程安全类常采用的技术如下:
- 实例封闭
当一个对象被封装到另一个对象中时,能够访问被封装对象的所有代码路径都是已知的。与对象可以由整个程序访问的情况相比,更易于对代码进行分析。通过将封闭机 制与合适的加锁策略结合起来,可以确保以线程安全的方式来使用非线程安全的对象。
对象一般可以封闭在三种地方:
- 封闭在类的一个实例中,例如作为类的一个私有成员。
- 封闭在某个作用域内,例如作为一个局部变量。
- 封闭在线程内,例如在某个线程中将对象从一个方法传递到另一个方法,而不是在多个线程之间共享该对象。
在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章的更多相关文章
- JAVA并发编程实战---第二章:线程安全性
对象的状态是指存储在状态变量中的数据.对象的状态可能包括其他依赖对象的域.例如HashMap的状态不仅存储在HashMap本身,还存储在许多Map.Entry对象中.对象的状态中包含了任何可能影响其外 ...
- Java并发编程实战3章
1.同步包括两方面:原子性和可见性. 2.可见性:因为在多线程程序中,如果没有采用正确的同步,有些线程就会得到失效数据. Java内存模型要求,变量的读取操作和写入操作都必须是原子操作,但对于非vol ...
- Java并发编程实战---第六章:任务执行
废话开篇 今天开始学习Java并发编程实战,很多大牛都推荐,所以为了能在并发编程的道路上留下点书本上的知识,所以也就有了这篇博文.今天主要学习的是任务执行章节,主要讲了任务执行定义.Executor. ...
- 《Java并发编程实战》/童云兰译【PDF】下载
<Java并发编程实战>/童云兰译[PDF]下载链接: https://u253469.pipipan.com/fs/253469-230062521 内容简介 本书深入浅出地介绍了Jav ...
- 《java并发编程实战》笔记
<java并发编程实战>这本书配合并发编程网中的并发系列文章一起看,效果会好很多. 并发系列的文章链接为: Java并发性和多线程介绍目录 建议: <java并发编程实战>第 ...
- Java并发编程实战 03互斥锁 解决原子性问题
文章系列 Java并发编程实战 01并发编程的Bug源头 Java并发编程实战 02Java如何解决可见性和有序性问题 摘要 在上一篇文章02Java如何解决可见性和有序性问题当中,我们解决了可见性和 ...
- Java并发编程实战 04死锁了怎么办?
Java并发编程文章系列 Java并发编程实战 01并发编程的Bug源头 Java并发编程实战 02Java如何解决可见性和有序性问题 Java并发编程实战 03互斥锁 解决原子性问题 前提 在第三篇 ...
- Java并发编程实战 05等待-通知机制和活跃性问题
Java并发编程系列 Java并发编程实战 01并发编程的Bug源头 Java并发编程实战 02Java如何解决可见性和有序性问题 Java并发编程实战 03互斥锁 解决原子性问题 Java并发编程实 ...
- Java并发编程实战——读后感
未完待续. 阅读帮助 本文运用<如何阅读一本书>的学习方法进行学习. P15 表示对于书的第15页. Java并发编程实战简称为并发书或者该书之类的. 熟能生巧,不断地去理解,就像欣赏一部 ...
随机推荐
- MyBatis常用对象SqlSessionFactory和SqlSession介绍和运用
学习框架一个比较好的路径阅读源码.本文介绍的SqlSessionFactory和SqlSession.可以通过了解SqlSessionFactory接口和SqlSession接口以及两个的实现类入手, ...
- PyQt5资料
http://bbs.fishc.com/thread-59816-1-1.html https://pypi.python.org/pypi/PyQt5/ http://www.thehackeru ...
- Spring Boot注解(annotation)列表
(1)@SpringBootApplication 申明让spring boot自动给程序进行必要的配置,这个配置等同于: @Configuration ,@EnableAutoConfigurati ...
- 【NLP+Deep learning】好文
http://blog.jobbole.com/77709/ 原文出处: http://colah.github.io/posts/2014-07-NLP-RNNs-Representations/
- 转载 --iOS实用小技巧(2)-生成txt文本
//不论是创建还是写入只需调用此段代码即可 如果文件未创建 会进行创建操作 - (void)writeToFileWithTxt:(NSString *)string{ dispatch_async( ...
- pybot/robot命令参数说明【dos下执行命令pybot.bat --help查看】
Robot Framework -- A generic test automation framework Version: 3.0 (Python 3.4.0 on win32) Usage: r ...
- JZOJ.5327【NOIP2017模拟8.21】四驱兄弟
Description
- ios 如何改变UISegmentedControl文本的字体大小?
UIFont *Boldfont = [UIFont boldSystemFontOfSize:16.0f]; NSDictionary *attributes = [NSDictionary dic ...
- android studio升级时提示 Connection failed. Please check your network connection and try again
原文地址 http://www.eyeapk.com/android-studio-update.html Mac OSX中修改文件路径为 bin/idea.vmoptions ,添加如下内容,如果无 ...
- 逐一取Map值
String[] mKeys = starDetil.getRows().keySet().toArray(new String[starDetil.getRows().size()]); starD ...