您的位置:首页 > 编程语言 > Java开发

Java并发中的几个基本概念

2018-02-11 16:26 281 查看

1. synchronized

synchronized方法的锁,就是该方法所在的对象本身

静态synchronized方法从Class对象上获取锁

每个Java对象都可以作为同步锁使用

内置锁(intrinsic locks)

监视器锁(monitor locks)

互斥锁(mutual exclusion lock,Mutex)

可重入(Reentrancy)

持有锁的线程

对应的计数器,请求计数器(acquisition count)

临界区

内存可见性

重排序(reordering)

过期数据

JVM 32 slot

导致64位变量并发不安全

同步

线程A执行一个同步块时,线程B随后也进入同一个临界区

则A在同步块之中/之前的操作,对B都是可见的

2. volatile

同步的弱形式

确保对一个变量的更新以可预见的方式告知其他的线程

共享变量

不会重排序

不会缓存在寄存器

不会缓存在处理器中

读取时,总会返回某个线程所写入的最新值

轻量级的同步机制

不会引发线程阻塞

不会加锁

通常当作标志使用

完成

中断

状态

加锁可以保证

可见性

原子性

volatile

可见性

单写多读

3. 发布/逸出

使数据/对象能够被当前范围之外的代码所使用,称为发布

一个对象在尚未准备好时就发布出去,称为逸出

间接发布

get方法直接返回引用

内部类中this逸出(构造器中的this)

构造器中将内部类发布出去

使用内部final变量 + 工厂方法来避免

对象初始化过程的同步

变量的默认初始值

相当于两次赋值

安全发布

通过静态初始化器初始化对象的引用

将它的引用存储到volatile域或AtomicReference

将它的引用存储到正确创建的对象的final域中

将它的引用存储到由锁正确保护的域中

4. 线程封闭

数据总是在同一个线程中被访问,就不需要任何同步

如:Swing中的invokeLater机制

在事件线程中安排执行Runnable

池化

资源在同一时间点,只能分配给一个线程使用

Ad-hoc 线程限制

维护线程限制性的任务都由开发人员来实现

易损性

未经过设计而得到的线程封闭行为

栈限制

局部变量都在线程栈中

其他线程无法访问

引用的对象,还是需要额外的同步机制

ThreadLocal

降低重用性

不可滥用

5. 不可变性

创建后状态不能被修改的对象,称为:不可变对象

线程安全

注意this逸出问题

final 域

初始化安全性

6. 同步器(Synchronizer)

用来调节相互协作的线程间的控制流

同步容器

早期JDK

Vector

Hashtable

Collections.synchronizedXxx
工厂方法

使用自身作为锁(
synchronized


并发性弱

锁竞争激烈

吞吐量低

Iterator

单线程中可在遍历过程中,对内容增减

但多线程中,由于可见性等问题,仍然无法避免并发问题

多线程场景中,即便使用Iterator,仍然需要考虑同步机制

fail-fast

ConcurrentModificationException

并发容器

Queue

ConcurrentLinkedQueue

FIFO

PriorityQueue

优先级

非并发

BlockingQueue

生产者-消费者

异步

解耦

需要考虑:是否有界

防止程序过载,耗尽内存

FIFO队列

LinkedBlockingQueue

ArrayBlockingQueue

优先级队列

PriorityBlockingQueue

ConcurrentHashMap

锁策略

分段锁

链表尾部加锁(Java 8)

迭代器弱一致性

无法客户端加锁

CopyOnWriteArrayList

写时复制

避免在迭代期间对容器加锁和复制

不可变数据的线程安全特性

复制带来额外开销

数组复制

数据量比较大时,性能开销大

同步器队列

SynchronousQueue

维护一个排队的线程清单

Blocking

没有存储功能

Deque

BlockingDeque

窃取工作

work-stealing

同步器

阻塞队列(BlockingQueue)

闭锁(latch)

阻塞一组线程,直到某些事件发生

CountDownLatch

FutureTask

变相闭锁

一旦进入完成状态,会永远停止在这个状态上

信号量(semaphore)

用来控制同时访问某特定资源的活动的数量

管理着一个有效的许可(permit)集

二元信号量

计数初始值为:1

变相的:互斥锁

不可重入锁

栅栏(barrier)

阻塞一组线程,直到所有的线程到达

闭锁等待事件,栅栏等待线程

CyclicBarrier

await
会给每一个线程返回一个唯一的到达索引号

可用于选举

Exchanger

变相栅栏

相位(phaser)

7. 任务(task)

抽象、离散的工作单元

清晰的任务边界(task boundaries)

资源隔离

独立性

并不依赖于其他任务的状态、结果或者边界效应(side effect)

独立有利于并发性

Runnable

8. Executor 框架

管理两种资源

任务

类型

Runnable

Callable

任务队列

BlockQueue

线程

线程工厂

线程池

ThreadPoolExecutor

ScheduledThreadPoolExecutor

ForkJoinPool

将任务与线程解耦

提供统一地生命周期/回调

执行策略

任务在什么(++what++)线程中执行

任务以什么(++what++)顺序执行(FIFO,LIFO,优先级)

可以有多少个(++how many++)任务并发执行

可以有多少个(++how many++)任务进入等待执行队列

如果系统过载,需要放弃一个任务,应该挑选哪一个(++which++)任务

如何(++how++)通知应用程序知道这一切

在一个任务的执行前与结束后,应该做什么(++what++)处理

生命周期

ExecutorService的3种状态

运行(running)

关闭(shutting down)

List<Runnable> shutdownNow()


boolean isShutdown()


boolean isTerminated()


boolean awaitTermination(long timeout, TimeUnit unit)


终止(termination)

任务

创建

提交

开始

完成

拒绝执行处理器

java.util.concurrent.RejectedExecutionHandler


周期性任务

ScheduledThreadPoolExecutor

异步任务处理

java.util.concurrent.ExecutorCompletionService<V>


任务队列

无限队列

ArrayBlockingQueue


LinkedBlockingQueue


PriorityBlockingQueue


有限队列

同步移交

饱和策略

9. 中断

处理可取消

用户请求取消

限时活动

应用程序事件

错误

关闭

没有绝对安全的停止线程的方法

相互协作的机制

大循环/关键步骤的重要检查点:线程是否中断

api

public boolean isInterrupted()


public void interrupt()


public static boolean interrupted()


中断策略

最有意义的是对线程级(thread-level)和服务级(service level)取消的规定

尽可能迅速退出

如需清理,尽可能通知相关实体

此线程已经退出

区分任务和线程对中断的反应

通过Future取消任务

通过致命药丸关闭线程

无界队列

显式Lock提供
lockInterruptibly
在锁等待时,还能响应中断

定制
newTaskFor
方法,来封装非标准的取消动作

10. 异常

UncaughtExeceptionHandler
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  java 并发