java并发编程实战:第四章----对象的组合
一、设计线程安全的类
- 找出构造对象状态的所有变量(若变量为引用类型,还包括引用对象中的域)
- 约束状态变量的不变性条件
- 建立对象状态的并发访问管理策略(规定了如何维护线程安全性)
1、收集同步需求(找出复合操作、多个变量遵循原子性的操作等)
2、依赖状态的操作(找出操作是否基于先验条件,例:取出当队列不为空)
3、状态的所有权(对象被哪些线程所有,哪些线程可以操作对象)
二、实例封闭
将数据封装在对象内部,可以将数据的访问限制在对象的方法上,确保简单正确的持有锁。(因为无需观察整个程序,只需检查当前类)
Java提供包装器对ArrayList、HashMap等容器对象提供线程安全保护
1、Java监视器模式:把对象的所有可变状态封装起来,并使用对象的内置锁保护
使用私有锁而不是内置锁的优点:(private final Object myLock = new Object();)
- 私有锁可以将锁封装起来,客户代码无法得到锁
- 客户可以通过公有方法来访问锁,以便参与到同步策略中去。
2、实例:基于监视器模式的车辆追踪

MutablePoint不一定是线程安全的,但该类一定是线程安全的,因为它包含的Map对象与Map中的Point对象都未曾发布,并且满足实例封闭。
三、线程安全性的委托
通过多个线程安全的类组成的类不一定是线程安全的
委托:通过委托类的线程安全性判断被委托类的线程安全性
1、委托给单个线程安全状态变量可以保证线程安全性
2、委托给多个相互独立的线程安全状态变量可以保证线程安全性
3、如果类包含多个线程安全状态变量的符合操作,则无法保证线程安全性,可以通过加锁机制保证
4、发布:如果一个状态变量是线程安全的,并且没有不变性条件约束它(例:大于0),在变量操作上没有不允许的状态转换,则可以安全发布
5、安全发布底层状态的线程安全类
1 @ThreadSafe
2 public class PublishingVehicleTracker {
3 private final Map<String, SafePoint> locations;
4 private final Map<String, SafePoint> unmodifiableMap;
5
6 public PublishingVehicleTracker(Map<String, SafePoint> locations) {
7 this.locations = new ConcurrentHashMap<String, SafePoint>(locations);
8 this.unmodifiableMap = Collections.unmodifiableMap(this.locations);
9 }
10
11 public Map<String, SafePoint> getLocations() {
12 return unmodifiableMap;
13 }
14
15 public SafePoint getLocation(String id) {
16 return locations.get(id);
17 }
18
19 public void setLocation(String id, int x, int y) {
20 if (!locations.containsKey(id))
21 throw new IllegalArgumentException("invalid vehicle name: " + id);
22 locations.get(id).set(x, y);
23 }
24 }
四、现有的线程安全类中添加功能
例:在Vector中添加”若没有则添加“功能,可以使用拓展的办法,BetterVector继承至Vector并对该符合操作通过同步机制增加原子性
1、客户端加锁机制
使用某个对象的代码时必须使用该对象本身用于保护其状态的锁,不推荐(同步的实现被分到两个不相关的类中)
当没有使用同一个锁,不足以提供线程安全保护:

2、组合
ImprovedList将List的操作委托给底层的list实例来操作,并通过自身的内置锁增加一层额外的加锁,同时添加了新的同步方法。

五、将同步策略文档化
java并发编程实战:第四章----对象的组合的更多相关文章
- Java并发编程实战 第4章 对象的组合
Java监视器模式 java监视器模式就是在将共享的数据封装在一个类里面,然后然后所有访问或者修改这些数据的方法都标注为synchronize. 车辆追踪模拟: 使用监视器模式: CarTracker ...
- Java并发编程实战 第3章 对象的共享
可见性 可见性是由于java对于多线程处理的内存模型导致的.这似乎是一种失败的设计,但是JVM却能充分的利用多核处理器的强大性能,例如在缺乏同步的情况下,Java内存模型允许编译器对操作顺序进行重排序 ...
- 【JAVA并发编程实战】2、对象的组合
1. 设计线程安全的类 1.找出构成对象状态的所有变量 2.找出约束状态变量的不变性条件 3.建立对象状态的并发访问管理策略 package cn.xf.cp.ch04; /** * *功能:JAVA ...
- Java并发编程实战---第六章:任务执行
废话开篇 今天开始学习Java并发编程实战,很多大牛都推荐,所以为了能在并发编程的道路上留下点书本上的知识,所以也就有了这篇博文.今天主要学习的是任务执行章节,主要讲了任务执行定义.Executor. ...
- Java并发编程实战 第16章 Java内存模型
什么是内存模型 JMM(Java内存模型)规定了JVM必须遵循一组最小保证,这组保证规定了对变量的写入操作在何时将对其他线程可见. JMM为程序中所有的操作定义了一个偏序关系,称为Happens-Be ...
- 【java并发编程实战】第一章笔记
1.线程安全的定义 当多个线程访问某个类时,不管允许环境采用何种调度方式或者这些线程如何交替执行,这个类都能表现出正确的行为 如果一个类既不包含任何域,也不包含任何对其他类中域的引用.则它一定是无状态 ...
- Java并发编程实战 第8章 线程池的使用
合理的控制线程池的大小: 下面内容来自网络.不过跟作者说的一致.不想自己敲了.留个记录. 要想合理的配置线程池的大小,首先得分析任务的特性,可以从以下几个角度分析: 任务的性质:CPU密集型任务.IO ...
- 读书笔记-----Java并发编程实战(二)对象的共享
public class NoVisibility{ private static boolean ready; private static int number; private static c ...
- JAVA并发编程实战---第三章:对象的共享(2)
线程封闭 如果仅仅在单线程内访问数据,就不需要同步,这种技术被称为线程封闭,它是实现线程安全性的最简单的方式之一.当某个对象封闭在一个线程中时,这种方法将自动实现线程安全性,即使被封闭的对象本生不是线 ...
- JAVA并发编程实战---第三章:对象的共享
在没有同步的情况下,编译器.处理器以及运行时等都可能对操作的执行顺序进行一些意想不到的调整.在缺乏足够同步的多线程程序中,要对内存操作的执行顺序进行判断几乎无法得到正确的结果. 非原子的64位操作 当 ...
随机推荐
- 利用WeX5给手机APP增加短信验证码功能
帖子来源:http://bbs.wex5.com/thread-70908-1-1.html 遇到一个手机APP项目客户要求注册到APP上的用户手机号必须是真实的通过X5平台整合短信发送平台接口完成了 ...
- 2018 Multi-University Training Contest 2-1007(hdu 6315)-题解
一.题意 给定一个元素个数为$N(1 \le N \le 10^5)$初始序列$a$和$b$,$a$序列的初始值全为$0$,$b$序列的初始值为$1$到$N$的一个排列.有$T(1 \le T \le ...
- ubuntu 下出现E: Sub-process /usr/bin/dpkg returned an error code
在用apt-get安装软件时出现了类似于 install-info: No dir file specified; try –help for more information.dpkg:处理 get ...
- Linux安装imagick扩展出现错误:configure: error: not found. Please provide a path to MagickWand-config or Wand-config program.
在Linux(CentOS)上安装imagick扩展时,遇到如下错误: checking ImageMagick MagickWand API configuration program... che ...
- ThreadPoolExecutor – Java Thread Pool Example
https://www.journaldev.com/1069/threadpoolexecutor-java-thread-pool-example-executorservice Java t ...
- 通过PicturreId获取图片路径(Url)
1.直接使用接口服务 _pictureService.GetPictureUrl((int)entity.SponsorPictureId); //entity是具体查询出来的实体对象 Sponsor ...
- oracle 截取字符(substr),检索字符位置(instr)
常用函数:substr和instr 1.SUBSTR(string,start_position,[length]) 求子字符串,返回字符串 解释:string 元字符串 start_posit ...
- msxml3.dll 执行页内操作时的错误
msxml3.dll 执行页内操作时的错误 regsvr32 msxml3.dll报错
- 跟我学算法- tensorflow 卷积神经网络训练验证码
使用captcha.image.Image 生成随机验证码,随机生成的验证码为0到9的数字,验证码有4位数字组成,这是一个自己生成验证码,自己不断训练的模型 使用三层卷积层,三层池化层,二层全连接层来 ...
- 6-关于#include<bits/stdc++.h>
万能头文件#include<bits/stdc++.h> (转载) 最近在打cf时赛后翻阅别人的代码总是会发现一个陌生而奇怪的头文件#include<bits/stdc++.h& ...