1、设计线程安全类的过程

设计线程安全类的过程就是设计对象状态并发访问下线程间的协同机制(在不破坏对象状态变量的不变性条件的前提下)。

(1)构建线程安全类的三个基本要素:

1)找出构成对象状态的所有变量;(确定状态变量的类型(共享、可变的、不可变的),针对不同类型的状态变量采用不同的并发访问策略)

2)找出约束对象状态变量的不变性条件;(不变性条件本质上就是确定状态变量自身的约束条件和状态变量间的依赖关系)

对象状态变量的不变性条件与后验条件约束了在对象状态上有哪些状态和状态转换是有效的,也就是对象状态变量的值哪些是有效的,哪些状态之间的转换时有效的,而哪些状态变量值和哪些状态间的转换时无效的。

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

同步策略:定义了如何在不违背不破坏对象不可变性或后验性的情况下对其状态的访问操作进行协同,规定了如何将不可变性、线程封闭、加锁机制等结合起来已维护线程的安全性,并且还规定了哪些变量由哪些锁来保护。

(2)构建线程安全类的过程

1)收集同步需求

确定构成对象状态的所有变量和对象状态变量不可变性条件的过程。

2)依赖状态的操作

在依赖对象状态的操作上(比如先验条件)如何设计,最简单的办法是通过现有库中的类来实现依赖状态的行为。

3)状态的所有权

确定状态变量如何共享和发布

2、构建线程安全类的三种方法:

(1)构建线程安全类的最简单方式:实例封闭

将数据封装在对象的内部,可以将数据的访问限制在对象的方法上,从而更容易确保线程在访问数据时总能持有正确的锁。

封闭机制和加锁机制结合起来,就可以确保以线程安全的方式使用非线程安全的对象

Java监视器模式:封装对象的所有可变状态,并有对象自己的内置锁来保护。

(2)组合多个类构建线程安全类(线程安全性的委托)

1)单个状态变量情况下

将单个状态变量委托给线程安全的类(如ConcurrentHashMap等)

2)多个状态变量且没有不可变性的约束下

每个状态变量都交给一个线程安全类维护

3)多个状态变量且存在不可变性的约束

委托和加锁机制联合起来才能实现在构建线程安全类的过程中不破坏多个状态变量不可变性条件。

4)发布底层的状态变量

如果一个类由多个独立且线程安全的状态变量组成,并且在所有的操作中都不含无效的状态转换,那么可以将线程安全性委托给底层的状态变量。

底层状态变量的发布:如果一个状态变量是线程安全的类,并且没有任何不变性条件来约束它的值,在变量的操作上也不存在任何不允许的状态转换,那么就可以安全的发布这个变量。

(3)在现有线程安全类中添加功能以构建新的线程安全类

1)修改现有线程安全类代码,新增功能

2)扩展现有线程安全类

3)使用辅助类扩展类的功能

4)组合

3、线程安全类的维护

将同步策略文档化

4.构建线程安全性委托的基础构建模块

(1)同步容器类

同步容器只有所有对容器状态的访问操作都串行化,才能实现他们的线程安全性。在并发的环境中,访问容器的状态在客户端没有加锁的情况下不是线程安全的。

实现线程安全的方式:封装容器的状态,把所有公有的的方法都进行同步,使得每次只有一个线程可以访问容器的状态。

缺点:严重降低并发性,吞吐量低

(2)并发容器

(1)ConCurrentHashMap

(2)CopyOnWriteArrayList

(3)阻塞队列和生产者-消费者模式

(1)BlockingQueue 阻塞队列:适用于生产者-消费者模式(消费者共享一个工作队列)

(2)BlockingDeque 阻塞双端队列:适用于工作密取模式(每个消费者都有一个自己的双端队列,当自己的双端队列完成后消费者可以从其他消费者的双端队列内获取)

工作密取模式比生产者-消费者模式更具可伸缩性,因为工作密取的每个消费者都有自己的工作队列,就减少了在因共享队列上因获取的数据而发生的竞争。

(4)阻塞方法和中断方法

(5)同步工具类

(1)CountDownLatch

(2)FutureTask

(3)Semaphore

(4)CyclicBarrier和Exchanger

(6)构建高效且可伸缩的结果缓存

那些年读过的书《Java并发编程实战》二、如何设计线程安全类的更多相关文章

  1. 《Java并发编程实战》学习笔记 线程安全、共享对象和组合对象

    Java Concurrency in Practice,一本完美的Java并发参考手册. 查看豆瓣读书 推荐:InfoQ迷你书<Java并发编程的艺术> 第一章 介绍 线程的优势:充分利 ...

  2. 读书笔记-----Java并发编程实战(一)线程安全性

    线程安全类:在线程安全类中封装了必要的同步机制,客户端无须进一步采取同步措施 示例:一个无状态的Servlet @ThreadSafe public class StatelessFactorizer ...

  3. 《Java并发编程实战》第二章 线程安全性 读书笔记

    一.什么是线程安全性 编写线程安全的代码 核心在于要对状态訪问操作进行管理. 共享,可变的状态的訪问 - 前者表示多个线程訪问, 后者声明周期内发生改变. 线程安全性 核心概念是正确性.某个类的行为与 ...

  4. 《Java并发编程实战》第二章 线程安全 札记

    一个.什么是线程安全 编写线程安全的代码 其核心是管理国事访问的操作. 共享,可变的状态的訪问 - 前者表示多个线程訪问, 后者声明周期内发生改变. 线程安全性 核心概念是正确性.某个类的行为与其规范 ...

  5. java并发编程实战:第二章----线程安全性

    一个对象是否需要是线程安全的取决于它是否被多个线程访问. 当多个线程访问同一个可变状态量时如果没有使用正确的同步规则,就有可能出错.解决办法: 不在线程之间共享该变量 将状态变量修改为不可变的 在访问 ...

  6. Java并发编程实战 第8章 线程池的使用

    合理的控制线程池的大小: 下面内容来自网络.不过跟作者说的一致.不想自己敲了.留个记录. 要想合理的配置线程池的大小,首先得分析任务的特性,可以从以下几个角度分析: 任务的性质:CPU密集型任务.IO ...

  7. Java并发编程实战(5)- 线程生命周期

    在这篇文章中,我们来聊一下线程的生命周期. 目录 概述 操作系统中的线程生命周期 Java中的线程生命周期 Java线程状态转换 运行状态和阻塞状态之间的转换 运行状态和无时限等待状态的切换 运行状态 ...

  8. Java 并发编程(三)为线程安全类中加入新的原子操作

    Java 类库中包括很多实用的"基础模块"类.通常,我们应该优先选择重用这些现有的类而不是创建新的类.:重用能减少开发工作量.开发风险(由于现有类都已经通过測试)以及维护成本.有时 ...

  9. 《Java并发编程实战》第八章 线程池的使用 读书笔记

    一.在任务与运行策略之间的隐性解耦 有些类型的任务须要明白地指定运行策略,包含: . 依赖性任务.依赖关系对运行策略造成约束.须要注意活跃性问题. 要求线程池足够大,确保任务都能放入. . 使用线程封 ...

  10. Java并发编程(十)设计线程安全的类

    待续... 线程安全的类 之前学了很多线程安全的知识,现在导致了我每次用一个类或者做一个操作我就会去想是不是线程安全的.如果每次都这样的考虑的话就很蛋疼了,这里的思路是,将现有的线程安全组件组合为更大 ...

随机推荐

  1. Java数据类型转换规则

  2. halcon区域运算

    区域运算: Ø 并:union1().union2(): Ø 交:intersection(); Ø 差:difference(); Ø 补:complement():

  3. How to get all Errors from ASP.Net MVC modelState?

    foreach (ModelState modelState in ViewData.ModelState.Values) { foreach (ModelError error in modelSt ...

  4. android SQLite数据库的基本操作

    SQLite是Android使用的轻量级的数据库,开发Android应用是对数据库的操作自然是必不可少. Android提供了一个SQLiteOpenHelper类来可以很方便的操作数据库, 继承和扩 ...

  5. Java -- 异常的捕获及处理 -- 异常类的继承结构

    7.1.3 异常类的继承结构 在整个Java的异常结构中,实际上有两个最常用的类,分别为Exception和Error,这两个类全都是Throwable的子类. ⊙ Exception : 一般标识的 ...

  6. Python标准输出重定向

    目录 Python标准输出重定向 声明 一. 背景知识 二. 重定向方式 2.1 控制台重定向 2.2 print >>重定向 2.3 sys.stdout重定向 2.4 上下文管理器(C ...

  7. [转]Mariadb的root密码忘记后的解决方法

    环境背景:CentOS 7.2     一.编辑/usr/lib/systemd/system/mariadb.service 文件,在Service段中添加 1 2 3 4 5 6 7 8 9 10 ...

  8. Gym 101149L Right Build

    L. Right Build time limit per test 2.0 s memory limit per test 256 MB input standard input output st ...

  9. C# 读写Excel的一些方法,Aspose.Cells.dll

    需求:现有2个Excel,一个7000,一个20W,7000在20W是完全存在的.现要分离20W的,拆分成19W3和7000. 条件:两个Excel都有“登录名”,然后用“登录名”去关联2个Excel ...

  10. Oracle数据库入门——sql语句和函数详解

    一.oracle常用数据类型 一.  数据定义语言(ddl) 数据定义语言ddl(data definition language)用于改变数据库结构,包括创建.更改和删除数据库对象. 用于操纵表结构 ...