《java并发编程实战》读书笔记3--对象的组合
希望将一些现有的线程安全组件组合为更大规模的组件或程序
设计线程安全的类
如果对象中所有的域是基本类型变量,那么这些域将构成对象的全部状态。例如,LinkedList的状态就包括该链表中所有节点对象的状态。要确保线程的安全性,就需要确保它的不变性条件不会在并发访问的情况下被破坏。
实例封闭
当一个对象被封装到另一个对象中时,能够访问被封装对象的所有代码路径都是已知的。通过将封闭机制与合适的加锁策略结合起来,可以确保以线程安全的方式来使用非线程安全的对象。被封闭对象一定不能超出它们既定的作用域。来个例子
如果Person类是可变的,那么在访问从PersonSet中获得的Person对象时,还需要额外的同步。在java平台的类库中有很多线程封闭的实例,其中有些类的唯一用途是将非线程安全的类转化为线程安全的类。一些基本容器类并非线程安全的,例如ArrayList和Hash,但类库提供了包装器工厂方法(例如Collections.synchronizedList及其类似方法),使得这些线程非安全的类可以在多线程环境中安全地使用。这些工厂方法通过“装饰器”模式将容器类封装在一个同步的包装器对象中,而包装器能将接口中的方法都实现为同步方法,并将调用请求转发到底层的容器对象上。只要包装器对象拥有对底层容器对象的唯一引用,那么他就是线程安全的。
java监视器模式
把所有可变状态都封装起来,并由对象自己的内置锁来保护。如:
看到了有意思的部分了:
使用私有锁而不是对象的内置锁(或任何其他可通过公有方式访问的锁), 有许多优点。私有的锁对象可以将锁封装起来,是客户代码无法得到锁,但客户代码可以通过公有方法来获得锁。这是书上的原话,然而看不懂....。首先要搞明白的是私有锁和内置锁的区别,在网上看到一篇不错的博文:http://www.jb51.net/article/56440.htm。
1. 类锁:在代码中的方法上加了static和synchronized的锁,或者synchronized(xxx.class)的代码段。
2.对象锁:在代码中的方法上加了synchronized的锁,或者synchronized(this)的代码段。
3.私有锁:在类内部声明一个私有属性如private Object lock,在需要加锁的代码段synchronized(lock)。
4.内置锁:每个java对象都可以用做一个实现同步的锁,这些锁成为内置锁。线程进入同步代码块或方法的时候会自动获得该锁,在退出同步代码块或方法时会释放该锁。获得内置锁的唯一途径就是进入这个锁的保护的同步代码块或方法。
看来内置锁和对象锁是一回事了,只不过角度不同定义自然不一样。
示例:车辆追踪
一个用于调度车辆的“车辆追踪器”,例如出租车,警车,货车等。首先使用监视器模式来构建车辆追踪器,然后在尝试放宽某些封装性需求同时又保持线程安全性。
执行更新操作的线程通过从GPS设备上获取的数据或者调度员从GUI界面上输入的数据来修改车辆的位置
视图线程与执行更新操作的线程将并发地访问数据模型,因此该模型必须是线程安全的,下面的程序给出了一个基于java监视器模式实现的“车辆追踪器”,其中使用了程序清单4-5中的MutablePoint来表示车辆的位置。
虽然类MutablePoint不是线程安全的,但追踪器类是线程安全的。它所包含的Map对象和可变的Ponit对象都未曾发布,当需要返回车辆的位置时,通过MutablePoint拷贝构造函数或者deepCopy方法来复制正确值,从而生成一个新的Map对象,并且该对象中的值与原有Map对象中的key和value值都相同。
线程安全性的委托
示例:基于委托的车辆追踪器
构造一个委托给线程安全类的车辆追踪器。将车辆的位置保存到一个Map对象中,因此首先要实现一个线程安全的Map类ConcurrentHashMap。还可以用一个不可变的类Point来代替MutablePoint以保存位置,
如果使用最初的MutablePoint类而不是Point类就会破坏封装性,因为getLocations会发布一个指向可变状态的引用。这里我对监视器模式和委托之间的区别的理解是:监视器将所有可变状态封装,对这些状态的操作利用内置锁保护起来。而委托模式则是将这些状态的安全性委托给一些线程安全的容器来保护。上面的代码还有一点要注意的是:getLocations返回的是一个不可修改但却实时的车辆位置视图。
独立的状态变量
将线程的安全性委托给多个状态变量。只要这些变量是彼此独立的。
当委托失效时
状态变量之间存在着某些不变性条件,如:
此时仅靠委托机制并不足以实现线程安全性,这个类必须提供自己的加锁机制。
发布底层的状态变量
示例:发布状态的车辆追踪器
在这个版本中发布底层的可变状态。
在现有的线程安全类中添加功能
简而言之就是利用java所提供的安全类库,再添加我们自己的类,来确保我们要实现的程序功能的线程安全性。
客户端加锁机制
参考:https://www.cnblogs.com/yaowen/p/5983136.html
组合
当为现有的类添加一个原子操作时,有一种更好的方法:组合。
使用了java监视器模式来封装了现有的List,只要在类中拥有指向底层List的唯一外部引用,就能确保线程安全性。(注意这里的底层List实例是私有不可变的)
心得:这章的主要内容是当多个对象组合在一起时如何确保其线程安全性。感觉这章真的是很抽象,说了很多理论性的东西,现在还是有很多不清楚,不明白的地方,还是得靠多实践才能加深理解。
《java并发编程实战》读书笔记3--对象的组合的更多相关文章
- Java并发编程实战 读书笔记(一)
最近在看多线程经典书籍Java并发变成实战,很多概念有疑惑,虽然工作中很少用到多线程,但觉得还是自己太弱了.加油.记一些随笔.下面简单介绍一下线程. 一 线程与进程 进程与线程的解释 个人觉 ...
- Java并发编程实战 读书笔记(二)
关于发布和逸出 并发编程实践中,this引用逃逸("this"escape)是指对象还没有构造完成,它的this引用就被发布出去了.这是危及到线程安全的,因为其他线程有可能通过这个 ...
- 【JAVA并发编程实战】2、对象的组合
1. 设计线程安全的类 1.找出构成对象状态的所有变量 2.找出约束状态变量的不变性条件 3.建立对象状态的并发访问管理策略 package cn.xf.cp.ch04; /** * *功能:JAVA ...
- Java并发编程实战 第4章 对象的组合
Java监视器模式 java监视器模式就是在将共享的数据封装在一个类里面,然后然后所有访问或者修改这些数据的方法都标注为synchronize. 车辆追踪模拟: 使用监视器模式: CarTracker ...
- 《java并发编程实战》笔记
<java并发编程实战>这本书配合并发编程网中的并发系列文章一起看,效果会好很多. 并发系列的文章链接为: Java并发性和多线程介绍目录 建议: <java并发编程实战>第 ...
- Java多线程编程实战读书笔记(一)
多线程的基础概念本人在学习多线程的时候发现一本书——java多线程编程实战指南.整理了一下书中的概念制作成了思维导图的形式.按照书中的章节整理,并添加一些个人的理解.
- 读书笔记-----Java并发编程实战(二)对象的共享
public class NoVisibility{ private static boolean ready; private static int number; private static c ...
- Java并发编程实践读书笔记(1)线程安全性和对象的共享
2.线程的安全性 2.1什么是线程安全 在多个线程访问的时候,程序还能"正确",那就是线程安全的. 无状态(可以理解为没有字段的类)的对象一定是线程安全的. 2.2 原子性 典型的 ...
- Java并发编程艺术读书笔记
1.多线程在CPU切换过程中,由于需要保存线程之前状态和加载新线程状态,成为上下文切换,上下文切换会造成消耗系统内存.所以,可合理控制线程数量. 如何控制: (1)使用ps -ef|grep appn ...
- Java并发编程实践读书笔记(2)多线程基础组件
同步容器 同步容器是指那些对所有的操作都进行加锁(synchronize)的容器.比如Vector.HashTable和Collections.synchronizedXXX返回系列对象: 可以看到, ...
随机推荐
- bzoj1656: [Usaco2006 Jan] The Grove 树木 (bfs+新姿势)
题目大意:一个n*m的图中,“.”可走,“X”不可走,“*”为起点,问从起点开始绕所有X一圈回到起点最少需要走多少步. 一开始看到这题,自己脑洞了下怎么写,应该是可过,然后跑去看了题解,又学会了一 ...
- bzoj1854: [Scoi2010]游戏(匈牙利) / GDKOI Day2 T2(最大流)
题目大意:有n(<=1000000)个装备,每个装备有两个属性值(<=10000),每个装备只能用一次,使用某一个值,攻击boss必须先使用属性为1的,再使用属性为2的,再使用属性为3的, ...
- 【单调队列】【P2627】 修剪草坪
传送门 Wa这次竟然不是Uva的题 Description 在一年前赢得了小镇的最佳草坪比赛后,Farm John变得很懒,再也没有修剪过草坪.现在,新一轮的最佳草坪比赛又开始了,Farm John希 ...
- Codeforces Round #337 (Div. 2)B
B. Vika and Squares time limit per test 2 seconds memory limit per test 256 megabytes input standard ...
- mesos安装、配置和运行
环境:rhel6.6 安装: 安装依赖包 yum install -y tar wget git which nss yum groupinstall -y "Development Too ...
- MEF——.NET中值得体验的精妙设计
摘要:.NET 是 Microsoft XML Web services 平台.MEF是.NET Framework 4.0一个重要的库,Visual Studio 2010 Code Editor的 ...
- MyBatis框架的使用及源码分析(十三) ResultSetHandler
在PreparedStatementHandler中的query()方法中,用ResultSetHandler来完成结果集的映射. public <E> List<E> que ...
- ZOJ3229 Shoot the Bullet [未AC]
Time Limit: 2 Seconds Memory Limit: 32768 KB Special Judge Gensokyo is a world which exist ...
- 基本控件文档-UIButton属性---iOS-Apple苹果官方文档翻译
本系列所有开发文档翻译链接地址:iOS7开发-Apple苹果iPhone开发Xcode官方文档翻译PDF下载地址 //转载请注明出处--本文永久链接:http://www.cnblogs.com/Ch ...
- python初步学习-python数据类型-集合(set)
集合 在已经学过的数据类型中: 能够索引的,如list/str,其中的元素可以重复 可变的,如list/dict,即其中的元素/键值对可以原地修改 不可变的,如str/int,即不能进行原地修改 无索 ...