引言

对象的组合,是《Java Concurrency in Practice》中第四章引入的课题。这并不是一个并发的概念。

为了可以将现有的线程安全组件组合为更大规模的组件或程序,而不是每次内存访问都进行分析以确保程序是线程安全的。这一章将介绍一些组合模式,这些模式可以更容易的使一个类成为线程安全的类,并且维护性更强。

一、设计线程安全的类

为了在不对整个程序进行分析的情况下就可以得出一个类是否是线程安全类的结论,总结了设计线程安全类的三个基本要素。

找出构成对象状态的所有变量。

找出约束状态变量的不变性条件

建立对象状态的并发访问管理策略。

 对象的状态指的是那些基本类型的变量。如果在对象的域中引用了其他对象,那么该对象的状态将包含被引用对象的域。

1.1 什么是同步策略?

同步策略的意思是保证对象不变性条件后验条件的前提下协同各个访问操作。是不变性条件、线程封闭、加锁机制、锁保护的相关概念的一个统称。

1.2 什么是不变性条件?

不变性条件指的是在对象状态空间内的一种逻辑约束。

状态空间简单的说就是对象的状态所有的可能值。而不变性条件就是人为规定的在状态空间内只能取哪些值。比如:

public class Counter {private long value = 0;public long increment() {if (value == Long.MAX_VALUE)throw new IllegalStateException("计数器溢出");return ++value;}
}

Counter类的对象有一个long类型的value,那么状态空间就是Long.MIN_VALUE 到 Long.MAX_VALUE之间所有的整型,但是由于该类的方法只提供了一个增长的方法,而value的初始值又是0,因此,对于这个类的不变性条件,就是value不能是负数。

1.3 状态迁移

对象的状态通过相关的方法产生了变化,这就是状态迁移。

1.4 后验条件

人为规定的状态迁移后的状态的有效性条件。比如上面的代码中,如果此时value是17,那么执行increment()后value一定要等于18。那么这里的后验条件就是状态改变后的值比状态改变前大1。

另外,当下一个状态需要依赖当前状态时,这个操作就必须是复合操作。但是,并不是所有操作都会在状态迁移上施加限制,例如,温度变量、彩票变量。

1.5 不变形条件与原子性

如果,不变性条件包含多个变量,那么将产生原子性的需求:这些相关的变量必须在单个原子操作中进行读取或更新。简单地说,就是不能先更新一个变量,然后释放锁,再获取锁,再去更新另一个相关变量。因为多个变量构成的不变性条件是整体性的,如果分开更新相关的状态,那么在中间的某个时刻必然会导致对象处于失效状态。

1.6 先验条件

简单地说就是,必须满足某种要求程序才能继续执行的条件。它属于一种依赖的状态。

单线程中的某个操作如果无法满足先验条件,则必然失败;多线程下可能会由于其他线程执行的操作而变为真。

并发程序中一定要等到先验条件为真,然后再执行该操作。这就引出了另一个相关的机制:Java的线程通信机制。比如等待和通知、阻塞等。

1.7 状态的所有权

对象对它封装的状态拥有所有权。所有权意味着控制权。

二、实例封闭(Instance Confinement)

如果某个对象不是线程安全的,有很多手段可以使它在多线程程序中正常使用。可以使用线程封闭技术确保这个对象只能由单个线程访问;或者通过锁来保护对象的所有访问。

其实,实例封闭技术在日常开发中经常使用。简单的说,对象A作为一个私有成员封装在了对象B中,那么对象A就是一个封闭的实例,A的访问也可以得到有效的控制。

例如下面的程序中,PersonSet的状态由HashSet来管理,而HashSet并非线程安全的。但由于mySet是私有的并且不会逸出,因此HashSet被封闭在PersonSet中。唯一能访问mySet的代码路径是addPerson与containsPerson,在执行它们时都要获得PersonSet上的锁。PersonSet的状态完全由它的内置锁保护,因而PersonSet是一个线程安全的类。

public class PersonSet {private final Set<Person> mySet = new HashSet<>();public synchronized void addPerson(Person p) {mySet.add(p);}public synchronized boolean containsPerson(Person p) {return mySet.contains(p);}
}

2.1 监视器模式

监视器模式并不是Java的GoF 23设计模式。什么是监视器模式?将对象的所有可变状态都封装起来,并且只能通过内置锁来访问,这就是监视器模式。而内置锁synchronized也成为监视器或监视器锁。

Java监视器模式只是一种编吗约定:对于任何一种锁对象,只要自始至终都使用该锁对象,都可以用来保护对象的状态。

监视器模式的两个代表:Vector和Hashtable。

2.2 私有锁对象

私有锁对象而不是对象的内置锁,可以将锁封装起来,使客户代码只能通过共有方法来访问锁。

public class PrivateLock {private final Object myLock = new Object();@GuardBy("myLock")Widget widget;void someMethod() {synchronized (myLock) {// 访问或修改Widget的状态}}
}

Java并发编程实战————对象的组合相关推荐

  1. Java并发编程实战笔记2:对象的组合

    设计线程安全的类 在设计现车让安全类的过程之中,需要包含以下三步: 找出构成对象状态的所有变量 找出约束状态变量的不变性条件 建立对象状态的并发访问策略 实例封闭 通过封闭机制与合适的加锁策略结合起来 ...

  2. java单线程共享,「Java并发编程实战」之对象的共享

    前言 本系列博客是对<Java并发编程实战>的一点总结,本篇主要讲解以下几个内容,内容会比较枯燥.可能大家看标题不能能直观的感受出到底什么意思,这就是专业术语,哈哈,解释下,术语(term ...

  3. JAVA并发编程实战——共享对象

    目录 思维导图 1. 可见性 1. 1 过期数据 1.2 锁和可见性 1.3 Volatile变量 2. 发布和逸出 2.1 安全构建实践 3. 线程封闭 3.1 栈限制 3.2 ThreadLoca ...

  4. 【极客时间】《Java并发编程实战》学习笔记

    目录: 开篇词 | 你为什么需要学习并发编程? 内容来源:开篇词 | 你为什么需要学习并发编程?-极客时间 例如,Java 里 synchronized.wait()/notify() 相关的知识很琐 ...

  5. 《Java 并发编程实战》--读书笔记

    Java 并发编程实战 注: 极客时间<Java 并发编程实战>–读书笔记 GitHub:https://github.com/ByrsH/Reading-notes/blob/maste ...

  6. Java并发编程实战————Executor框架与任务执行

    引言 本篇博客介绍通过"执行任务"的机制来设计应用程序时需要掌握的一些知识.所有的内容均提炼自<Java并发编程实战>中第六章的内容. 大多数并发应用程序都是围绕&qu ...

  7. Java并发编程实战————Semaphore信号量的使用浅析

    引言 本篇博客讲解<Java并发编程实战>中的同步工具类:信号量 的使用和理解. 从概念.含义入手,突出重点,配以代码实例及讲解,并以生活中的案例做类比加强记忆. 什么是信号量 Java中 ...

  8. Java并发编程实战_不愧是领军人物!这种等级的“Java并发编程宝典”谁能撰写?...

    前言 大家都知道并发编程技术就是在同一个处理器上同时的去处理多个任务,充分的利用到处理器的每个核心,最大化的发挥处理器的峰值性能,这样就可以避免我们因为性能而产生的一些问题. 大厂的核心负载肯定是非常 ...

  9. java并发编程实战学习(3)--基础构建模块

    转自:java并发编程实战 5.3阻塞队列和生产者-消费者模式 BlockingQueue阻塞队列提供可阻塞的put和take方法,以及支持定时的offer和poll方法.如果队列已经满了,那么put ...

最新文章

  1. 页面 切换 中英文 怎么实现_【完美解决】AE CC2018表达式错误 ae cc2018如何进行中英文转换?...
  2. 加密模式||填充模式
  3. DevExpress控件安装和初次使用图解
  4. android qq 进程保活,Android保活从入门到放弃:乖乖引导用户加白名单吧(附7大机型加白示例)...
  5. Android 项目中常用到的第三方组件
  6. 2010.7.29 模式对话框
  7. nsautoreleasepool研究
  8. Linux网络设备驱动程序
  9. 利用分类模型学习特征权重
  10. 非平稳序列的确定性分析
  11. windows service 2012阿里云服务器在搭建mysql时缺少msvcr100.dll文件解决方案
  12. 如何给PDF文件加密?PDF文件加密操作步骤来了
  13. android没有adm_这可能是安卓平台上最好的下载器:ADM
  14. 你创业为什么会失败?
  15. Java(Spring boot)实现生成二维码
  16. 【FPGA】串口以命令控制温度采集
  17. 编译原理:LL(1)语法分析器的实现(内含代码详细注释)
  18. [Android]Toolbar
  19. 通知公众平台php,微信公众平台开发模板消息
  20. 复旦大学新冠肺炎防控第一课——尔雅答案

热门文章

  1. observable_Java Observable setChanged()方法与示例
  2. Java夺命21连问!(附答案)
  3. netframework 4.0内置处理JSON对象
  4. SpringBoot中mybatis配置多数据源
  5. mysql count count id_mysql 为什么count(*)快于count(id)
  6. pythonrequests证书_python requests证书问题解决
  7. for循环如果先--_乐字节Java循环:循环控制和嵌套循环
  8. SpringBoot + Shiro 缓存记住密码
  9. 学习Spring Boot:(二十三)Spring Boot 中使用 Docker
  10. MySQL中实现并、交、差