Java并发编程实战
2021-11-28 20:53:53 43 举报
AI智能生成
Java并发编程实战
作者其他创作
大纲/内容
基础理论
3大问题
可见性
来源
CPU-内存-IO 速度差异
定义
线程A对CPU缓存的操作,线程B从主存获取最新
原子性
来源
线程切换
定义
不被中断的CPU指令
count++
有序性
来源
编译器优化
eg.不安全的单例
Java内存模型
来源
缓存-->可见性
编译器优化-->有序性
解决
JVM按需禁用
缓存&编译器优化
方法
volatile
synchronized
final
Happens-Before 规则
程序的顺序性规则
volatile 变量规则
传递性
管程中锁的规则
管程:通用的同步原语
Java:synchronized
线程 start() 规则
线程 join() 规则
锁 Lock
互斥锁
一个锁保护多个资源
细粒度锁
用不同的锁对受保护资源进行精细化管理,能够提升性能
覆盖所有资源
this->共享object->Class
死锁
定义
一组互相竞争资源的线程因互相等待,导致“永久”阻塞的现象。
如何预防死锁
4条件同时即死锁
互斥,共享资源 X 和 Y 只能被一个线程占用;
占有且等待,线程 T1 已经取得共享资源 X,在等待共享资源 Y 的时候,不释放共享资源 X;
不可抢占,其他线程不能强行抢占线程 T1 占有的资源;
循环等待,线程 T1 等待线程 T2 占有的资源,线程 T2 等待线程 T1 占有的资源,就是循环等待。
破坏任意一个条件
破坏占用且等待条件
可以一次性申请所有的资源
破坏不可抢占条件
占用部分资源的线程进一步申请其他资源时,如果申请不到,可以主动释放它占有的资源
破坏循环等待条件
可以靠按序申请资源来预防
“等待-通知”
关注问题
安全性问题
活跃性问题
性能问题
管程
MESA模型
互斥
同步
Java线程
并发工具
Lock和Condition
Lock
再造管程的理由
synchronized--死锁问题
互斥锁设计
能够响应中断
支持超时
非阻塞地获取锁
如何保证可见性
volatile 的 Happens-Before 规则
可重入锁
线程可以重复获取同一把锁
公平锁与非公平锁
公平锁
唤醒的策略就是谁等待的时间长
非公平锁
随机唤醒
最佳实践
永远只在更新对象的成员变量时加锁
永远只在访问可变的成员变量时加锁
永远不在调用其他对象的方法时加锁
Condition
利用两个条件变量实现阻塞队列
同步与异步
同步:调用方需要等待结果
异步:调用方不需要等待结果
异步实现
异步调用(调用方)
调用方创建一个子线程,在子线程中执行方法调用
异步方法(实现方)
方法实现的时候,创建一个新的线程执行主要逻辑,主线程直接 return
ReadWriteLock
什么是读写锁
允许多个线程同时读共享变量
只允许一个线程写共享变量
如果一个写线程正在执行写操作,此时禁止读线程读共享变量
快速实现一个缓存
实现缓存的按需加载
读写锁的升级与降级
锁的升级
锁的降级
StampedLock
3种模式
写锁
ReadWriteLock 的写锁
悲观读锁
ReadWriteLock 的读锁
乐观读
版本对比(无锁)
注意事项
StampedLock 不支持重入
悲观读/写锁都不支持条件变量
一定不要调用中断操作,除非调用可中断的读/写锁
readLockInterruptibly()
writeLockInterruptibly()
CountDownLatch和CyclicBarrier
CountDownLatch:一个线程等待多个线程
CyclicBarrier:一组线程之间互相等待
Semaphore-信号量
Exchanger-交换者
并发容器
List
CopyOnWriteArrayList
CopyOnWrite:写操作时候拷贝一份
适用场景
读多写少,容忍读写不一致
CopyOnWriteArrayList 迭代器是只读的,不支持增删改
Map
ConcurrentHashMap
key无序
ConcurrentSkipListMap
key有序
Set
ConcurrentSkipListSet
CopyOnWriteArraySet
Queue
BlockingDeque
BlockingQueue
ConcurrentLinkedQueue
ConcurrentLinkedDeque
原子类
基本数据类型
AtomicBoolean
AtomicInteger
AtomicLong
引用类型
AtomicReference
AtomicStampedReference
版本号解决ABA问题
AtomicMarkableReference
boolean值解决ABA问题
数组
AtomicIntegerArray
AtomicLongArray
AtomicReferenceArray
对象属性更新器
AtomicIntegerFieldUpdater
AtomicLongFieldUpdater
AtomicReferenceFieldUpdater
累加器
DoubleAccumulator
DoubleAdder
LongAccumulator
LongAdder
线程池与异步
Executor与线程池
缘由
线程是一个重量级的对象,应该避免频 繁创建和销毁
原理
生产者-消费者模式
参数
corePoolSize
线程池保有的最小线程数。
maximumPoolSize
线程池创建的最大线程数。
keepAliveTime & unit
> corePoolSize的线程,空闲指定时间后销毁
workQueue
工作队列
设置有界队列
threadFactory
自定义如何创建线程
handler
拒绝策略
CallerRunsPolicy
提交任务的线程自己去执行该任务。
AbortPolicy
默认的拒绝策略,会 throws RejectedExecutionException。
DiscardPolicy
直接丢弃任务,没有任何异常抛出。
DiscardOldestPolicy
丢弃老的任务。
执行任务
无返回结果
execute(Runnable command)
带返回结果
Future<?> submit(Runnable task)
没有返回值,Future仅仅用来判断任务已经结束了
<T> Future<T> submit(Callable<T> task)
Future.get()获取返回值
<T> Future<T> submit(Runnable task, T result)
result用于主/子线程间共享数据
Future
适用场景
简单并行任务,线程池 + Future
接口
boolean cancel(boolean mayInterruptIfRunning)
取消任务
boolean isCancelled()
判断任务是否已取消
boolean isDone()
判断任务是否已结束
get()
获取任务执行结果
get(long timeout, TimeUnit unit)
获取任务执行结果(超时内)
FutureTask
构造器
FutureTask(Callable<V> callable)
FutureTask(Runnable runnable, V result)
eg.
CompletableFuture
适用场景
任务间有聚合关系,AND 或 OR
CompletionService
Fork/Join
并发模式
Immutability模式
Copy-on-Write模式
ThreadLocal
使用示例
实现原理
线程池下的问题:内存泄漏
Guarded Suspension模式
Balking模式
Thread-Per-Message模式
Worker Thread模式
两阶段终止模式
生产者-消费者模式
协程
CSP模型
Actor 模型
不保证100%发送
不保证消息送达的顺序和发送的顺序是一致
不保证消息会被百分百处理
软件事务内存
0 条评论
下一页