java并发编程实践学习(2)--对象的组合
- 先验条件(Precondition):某些方法包含基于状态的先验条件。例如,不能从空队列中移除一个元素,在删除元素前队列必须处于非空状态。基于状态的先验条件的操作成为依赖状态操作。
- 在单线程中,如果某操作无法满足先验条件,就只能失败,但在并发程序中先验条件可能会由于其他线程执行的操作而变成真。
- java中等待某个条件为真的各种内置机制(包括等待和通知机制)都与内置加锁紧密关联。
- 所有权和封装性总是相关联的:对象封装它拥有的所有权,对象对它的封装的状态拥有所有权。
- 发布了某个可变对象的引用,那就不再拥有独占的控制权。
- 容器类通常表现出一种“所有权分离”的形式。
4.1设计线程安全的类
在设计线程安全类的过程中,需要包含以下三个基本要素:
- 找出构成对象状态的所有变量
- 找出约束状态变量的不可变性条件
- 建立对象状态的并发访问管理策略
4.3委托给线程安全的类
可以将共享资源委托给一个线程安全的类。比如ConcurrentHashMap,copyOnWriteArrayList.
如果一个类时由多个独立且线程安全的状态变量组成,并且在所有的操作中都不包含无效状态转换,那么可以将线程安全性委托给底层状态变量。
下面是一个监控车辆位置的实例。其中Point是线程安全不可变的类。
/**
* 不可变
*/
@Immutable
class Point{
public final int x,y; Point(int x,int y ) {
this.x = x;
this.y = y;
}
} /**
* 委托给线程安全类的车辆追踪器
*/
@ThreadSafe
class DelegatingVehicleTracker{
private final ConcurrentHashMap<String,Point> locations;
private final Map<String,Point> unmodifiableMap; public DelegatingVehicleTracker(Map<String,Point> points) {
this.locations = new ConcurrentHashMap<>(points);
this.unmodifiableMap = Collections.unmodifiableMap(locations);
} public Map<String,Point> getLocations(){
return unmodifiableMap;
} public Point getLocation(String id){
return locations.get(id);
} public void setLocation(String id,int x,int y){
if(locations.replace(id,new Point(x,y)) == null){
throw new IllegalArgumentException("invalid vehicle name:"+id);
}
}
}
如果一个状态变量是线程安全的,并且没有任何不变性条件来约束它的值,在变量的操作上也不存在任何不允许的状态转换,那么就可以安全地发布这个变量。
同样是车辆追踪,我想要获取位置,还可以修改位置,安全性问题可以交给底层SafePoint:
/**
* 线程安全且可变的Point类
*/
@ThreadSafe
class SafePoint{
@GuardedBy("this") private int x,y;
private SafePoint(int[] a){
this(a[0],a[1]);
}
public SafePoint(SafePoint p){
this(p.get());
}
public SafePoint(int x,int y){
this.x = x;
this.y = y;
}
public synchronized int[] get(){
return new int[] {x,y};
}
public synchronized void set(int x,int y){
this.x =x;
this.y = y;
}
} /**
* 安全发布底层状态的车辆追踪器
*/
@ThreadSafe
class PublishingVehicleTracker{
private final Map<String,SafePoint> locations;
private final Map<String,SafePoint> unmodifiableMap; PublishingVehicleTracker(Map<String, SafePoint> locations, Map<String, SafePoint> unmodifiableMap) {
this.locations = locations;
this.unmodifiableMap = unmodifiableMap;
} public Map<String,SafePoint> getLocations(){
return unmodifiableMap;
}
public SafePoint getLocation(String id){
return locations.get(id);
}
public void setLocation(String id,int x,int y){
if (!locations.containsKey(id))
throw new IllegalArgumentException("invalid vehicle name:"+id);
locations.get(id).set(x,y);
}
}
4.5将同步策略文档化
在文档中说明客户代码需要了解的线程安全性保证,以及代码维护人员需要了解的同步策略。
synchronized,volatile或者任何一个线程安全类都对应于某种同步策略,用于在并发访问时确保数据的完整性。一定要在忘记之前记录下来。
可以使用@GuardedBy("this")或者别的来注释锁。
java并发编程实践学习(2)--对象的组合的更多相关文章
- Java并发编程实战 之 对象的共享
上一篇介绍了如何通过同步多个线程避免同一时刻访问相同数据,本篇介绍如何共享和发布对象,使它们被安全地由多个进程访问. 1.可见性 通常,我们无法保证执行读操作的线程能看到其他线程写入的值,因为每个线程 ...
- JAVA并发编程学习笔记------对象的可见性及发布逸出
一.非原子的64位操作: 当线程在没有同步的情况下读取变量时,可能会得到一个失效值,但至少这个值是由之前某个线程设置的值,而不是一个随机值,这种安全性保证被称为最低安全性.最低安全性适用于绝大多数变量 ...
- 《Java并发编程实战》学习笔记 线程安全、共享对象和组合对象
Java Concurrency in Practice,一本完美的Java并发参考手册. 查看豆瓣读书 推荐:InfoQ迷你书<Java并发编程的艺术> 第一章 介绍 线程的优势:充分利 ...
- [Java 并发] Java并发编程实践 思维导图 - 第四章 对象的组合
依据<Java并发编程实践>一书整理的思维导图. 第一部分: 第二部分:
- Java 并发编程(四):如何保证对象的线程安全性
01.前言 先让我吐一句肺腑之言吧,不说出来会憋出内伤的.<Java 并发编程实战>这本书太特么枯燥了,尽管它被奉为并发编程当中的经典之作,但我还是忍不住.因为第四章"对象的组合 ...
- Java并发编程锁系列之ReentrantLock对象总结
Java并发编程锁系列之ReentrantLock对象总结 在Java并发编程中,根据不同维度来区分锁的话,锁可以分为十五种.ReentranckLock就是其中的多个分类. 本文主要内容:重入锁理解 ...
- 《Java并发编程实战》第三章 对象的共享 读书笔记
一.可见性 什么是可见性? Java线程安全须要防止某个线程正在使用对象状态而还有一个线程在同一时候改动该状态,并且须要确保当一个线程改动了对象的状态后,其它线程能够看到发生的状态变化. 后者就是可见 ...
- 【Java并发编程一】线程安全和共享对象
一.什么是线程安全 当多个线程访问一个类时,如果不用考虑这些线程在运行时环境下的调度和交替执行,并且不需要额外的同步及在调用代码代码不必作其他的协调,这个类的行为仍然是正确的,那么称这个类是线程安全的 ...
- Java并发编程(五):Java线程安全性中的对象发布和逸出
发布(Publish)和逸出(Escape)这两个概念倒是第一次听说,不过它在实际当中却十分常见,这和Java并发编程的线程安全性就很大的关系. 什么是发布?简单来说就是提供一个对象的引用给作用域之外 ...
随机推荐
- 怎样让.bat文件开机自启动
Windows Registry Editor Version 5.00 [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\R ...
- 搭建 SubversionEdge for VS
1. 需要软件 SubversionEdge , AnkhSvn,TortoiseSVN: 2. 安装3个软件,一路Next 3. 安装完SubversionEdge 后,会打开一个网页http:// ...
- iOS 项目改名~~~~~
今早出现一个改名的囧事...先记录下...在此之前感谢整理过这片文章的作者 --- GarveyCalvin ,插眼!以下是正文---- 前言:在iOS开发中,有时候想改一下项目的名字,都会遇到很多麻 ...
- innodb 锁分裂继承与迁移
innodb行锁简介 行锁类型 LOCK_S:共享锁 LOCK_X: 排他锁 GAP类型 LOCK_GAP:只锁间隙 LOCK_REC_NO_GAP:只锁记录 LOCK_ORDINARY: 锁记录和记 ...
- Intellij笔记
环境 官网: http://www.jetbrains.com/idea/download/ 需要Java的JDK,需要安装 JDK,而不是 JRE! http://www.oracle.com/te ...
- Fragment提交transaction导致state loss异常
下面自从Honeycomb发布后,下面栈跟踪信息和异常信息已经困扰了StackOverFlow很久了. java.lang.IllegalStateException: Can not perform ...
- Sqlserver 如何获取每组中的第一条记录
在日常生活方面,我们经常需要记录一些操作,类似于日志的操作,最后的记录才是有效数据,而且可能它们属于不同的方面.功能下面,从数据库的术语来说,就是查找出每组中的一条数据. 例子 我们要从上面获得的有效 ...
- 使用MYSQL命令直接导入导出SQL文件
很多时候,我们的数据开发都会用到很多开发利器,比如powerdesigner, navicat等这些软件,虽然好用,但是要收费,在公司里面是禁止使用盗版软件的,怕罚款各方面的,所以我们也不敢直接在公司 ...
- JQuery checkbox check/uncheck
想通过JQuery来check或者uncheck页面上的checkbox控件,我们可能会想到用下面的代码: $('#chk-all').on('click', function(){ var chec ...
- Yii 框架学习--01 框架入门
Yii 是一个高性能的,适用于开发 WEB2.0 应用的 PHP 框架. Yii目前有两个主要的版本: 2.0 和 1.1.本文以YII 2.0.7为例. 环境需求 Yii2.0 框架有一些系统上的需 ...