《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返回系列对象: 可以看到, ...
随机推荐
- Linux之同步互斥阻塞20160703
主要介绍一下Linux下的互斥与阻塞方面的知识: 1. 原子操作 原子操作指的是在执行过程中不会被别的代码路径所中断的操作. 常用原子操作函数举例: atomic_t v = ATOMIC_INIT( ...
- JavaScript身份证号码有效性验证
最近需要对身份证合法性进行验证,实名验证是不指望了,不过原来的验证规则太过简单,只是简单的验证了身份证长度,现在业务需要加强下身份证验证规则,网上找到了不少资料,不过都不合偶的心意,无奈只好直接写一个 ...
- 复习java数据库操作的总结
以前学习java数据库操作,学得那叫糊里糊涂,各种JDBC常用的类和接口根本是傻傻分不清啥是干嘛的.只是套着用用吧. 不过这次好歹清楚些了,呜呜,学习有阶段性,多次重复才有好效果,多么痛的领悟. 工程 ...
- Qt ------ 初始化构造函数参数,parent
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setup ...
- XSS攻击处理方案
1. XSS攻击基本概念 XSS是一种经常出现在web应用中的计算机安全漏洞,它允许恶意web用户将代码植入到提供给其它用户使用的页面中.比如这些代码包括HTML代码和客户端脚本.攻击者利用XSS漏洞 ...
- 实体框架(Entity Framework)快速入门--实例篇
在上一篇 <实体框架(Entity Framework)快速入门> 中我们简单了解的EF的定义和大体的情况,我们通过一步一步的做一个简单的实际例子来让大家对EF使用有个简单印象,看操作步骤 ...
- Centos下iptables常用命令
安装iptablesyum install iptables-services 重启防火墙使配置文件生效systemctl restart iptables.service 设置iptables防火墙 ...
- Android中禁止SlidingPaneLayout的侧滑功能
Android中使用android.support.v4.widget.SlidingPaneLayout实现侧滑功能的时候,可能出现滑动屏幕时与SlidingPaneLayout的侧滑发生冲突,查看 ...
- 好用的python库(转)
这个专区就是用来分享你在使用 Python 过程中发现的或者自己写的 Python 库.有时候一个好用的库将大大节省一个开发者的时间,也会让开发者多这个库的作者感激涕零的.例如我在开发 Pythonz ...
- 记一次rsync日志报错directory has vanished
中午两点的时候邮件告知rsync同部svn源库失败,看rsync日志报错显示如上,当时还在上课,没在公司,怀疑是不是有人动了svn的版本库,后来询问同事并通过vpn登录服务器上查看版本库是正常的,也没 ...