Chapter 16 . JUC 线程高级

2018-10-04  本文已影响8人  GeekGray

阅读原文

Chapter 16 . JUC 线程高级

16.1 Java JUC 简介

在 Java 5.0 提供了 java.util.concurrent (简称
JUC )包,在此包中增加了在并发编程中很常用
的实用工具类, 用于定义类似于线程的自定义子
系统,包括线程池、异步 IO 和轻量级任务框架。
提供可调的、灵活的线程池。还提供了设计用于
多线程上下文中的 Collection 实现等。


16.2 volatile 关键字 内存可见性

内存可见性(Memory Visibility)是指当某个线程正在使用对象状态
而另一个线程在同时修改该状态,需要确保当一个线程修改了对象
状态后,其他线程能够看到发生的状态变化。

可见性错误是指当读操作与写操作在不同的线程中执行时,我们无
法确保执行读操作的线程能适时地看到其他线程写入的值,有时甚
至是根本不可能的事情。

我们可以通过同步来保证对象被安全地发布。除此之外我们也可以
使用一种更加轻量级的 volatile 变量

volatile 关键字

Java 提供了一种稍弱的同步机制,即 volatile 变
量,用来确保将变量的更新操作通知到其他线程。
可以将 volatile 看做一个轻量级的锁,但是又与
锁有些不同:


16.3 原子变量 CAS算法

CAS 算法

CAS (Compare-And-Swap) 是一种硬件对并发的支持,针对多处理器
操作而设计的处理器中的一种特殊指令,用于管理对共享数据的并
发访问。

原子变量

类的小工具包,支持在单个变量上解除锁的线程安全编程。事实上,此包中的类可
将 volatile 值、字段和数组元素的概念扩展到那些也提供原子条件更新操作的类。


16 .4 ConcurrentHashMap 锁分段机制

Java 5.0 在 java.util.concurrent 包中提供了多种并发容器类来改进同步容器
的性能。

CountDownLatch 闭锁

Java 5.0 在 java.util.concurrent 包中提供了多种并发容器类来改进同步容器
的性能。


16.5 实现 Callable 接口

Java 5.0 在 java.util.concurrent 提供了一个新的创建执行
线程的方式: Callable 接口

Lock 同步锁

在 Java 5.0 之前,协调共享对象的访问时可以使用的机
制只有 synchronized 和 volatile 。 Java 5.0 后增加了一些
新的机制,但并不是一种替代内置锁的方法,而是当内
置锁不适用时,作为一种可选择的高级功能。

Condition 控制线程通信

Condition 接口描述了可能会与锁有关联的条件变量。这些变量在用
法上与使用 Object.wait 访问的隐式监视器类似,但提供了更强大的
功能。需要特别指出的是,单个 Lock 可能与多个 Condition 对象关
联。为了避免兼容性问题, Condition 方法的名称与对应的 Object 版
本中的不同。


16 .5 线程按序交替

ReadWriteLock 读写锁


16 .6 线程八锁

一个对象里面如果有多个synchronized方法,某一个时刻内,只要一个线程去调用
其中的一个synchronized方法了,其它的线程都只能等待,换句话说,某一个时刻
内,只能有唯一一个线程去访问这些synchronized方法

• 锁的是当前对象this,被锁定后,其它的线程都不能进入到当前对象的其它的
synchronized方法

• 加个普通方法后发现和同步锁无关

• 换成两个对象后,不是同一把锁了,情况立刻变化。

• 都换成静态同步方法后,情况又变化

• 所有的非静态同步方法用的都是同一把锁——实例对象本身,也就是说如果一个实
例对象的非静态同步方法获取锁后,该实例对象的其他非静态同步方法必须等待获
取锁的方法释放锁后才能获取锁,可是别的实例对象的非静态同步方法因为跟该实
例对象的非静态同步方法用的是不同的锁,所以毋须等待该实例对象已获取锁的非
静态同步方法释放锁就可以获取他们自己的锁。

• 所有的静态同步方法用的也是同一把锁——类对象本身,这两把锁是两个不同的对
象,所以静态同步方法与非静态同步方法之间是不会有竞态条件的。但是一旦一个
静态同步方法获取锁后,其他的静态同步方法都必须等待该方法释放锁后才能获取
锁,而不管是同一个实例对象的静态同步方法之间,还是不同的实例对象的静态同
步方法之间,只要它们同一个类的实例对象!


16 .7 线程池

第四种获取线程的方法:线程池,一个 ExecutorService,它使用可能的几个池线程之
一执行每个提交的任务,通常使用 Executors 工厂方法配置。


16 .8 ForkJoinPool 分支/合并框架 工作窃取

Fork/Join 框架:就是在必要的情况下,将一个大任务,进行拆分(fork)成
若干个小任务(拆到不可再拆时),再将一个个的小任务运算的结果进


Fork/Join 框架与线程池的区别

采用 “工作窃取”模式(work-stealing):

当执行新的任务时它可以将其拆分分成更小的任务执行,并将小任务加
到线程队列中,然后再从一个随机线程的队列中偷一个并把它放在自己的队
列中。

上一篇 下一篇

猜你喜欢

热点阅读