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位操作 当 ...
随机推荐
- C BIN加密
#include <stdio.h> #include <string.h> #include <stdlib.h> #ifndef DWORD #define D ...
- 移动端开发之px,em和rem详解
px:表示的是绝对的像素值,1px就是1像素大小 em:关于em,网上有资料说是关于父元素的,但是其实个人感觉这种说法是不对的,其实em的大小是根据自身的font-size确定的,而只是正常的情况下子 ...
- Android中Parcelable与Serializable接口用法
转自: Android中Parcelable接口用法 1. Parcelable接口 Interface for classes whose instances can be written to a ...
- SPM——How to use github
In this semester, we take a class called 'Software Project Management'. And in this class, we have l ...
- 224. Basic Calculator + 227. Basic Calculator II
▶ 两个四则表达式运算的题目,第 770 题 Basic Calculator IV 带符号计算不会做 Orz,第 772 题 Basic Calculator III 要收费 Orz. ▶ 自己的全 ...
- Redis 位操作
[Redis 位操作] 1.GETBIT key offset 对 key 所储存的字符串值,获取指定偏移量上的位(bit). 当 offset 比字符串值的长度大,或者 key 不存在时,返回 0 ...
- shell中比较字符串大小,>和<前需要加上\进行转义,否则会输出到文件了
遇到的问题:进行了目录的字符串大小比较,结果在目录下生成了很多的新文件 解决方法:在>和<的比较符号前增加\转义 代码如下: #/usr/bin/bash cd /opt/scf/se ...
- 读取指定路径的Properties文件
1.读取项目内的properties文件,项目内的properties文件一般都放在resource文件夹下面, 通过getClassLoader().getResourceAsStream()来获取 ...
- transform.rotation和GetComponent<Rigidbody>().MoveRotation
同时在UPDATE和FIXED UPDATE中调整 旋转 并未出现闪,而是一直以UPDATE中的为准,可认为MoveRotation调用后在UPDATE中生效 using System.Collect ...
- OGNL特殊符号的使用
---------------------siwuxie095 # 的使用 1.使用 # 获取 context 中的数据 「值栈分为 root 和 context 两部分」 2.如:向 Request ...