深入浅出 Java Concurrency
2020-05-27 21:39:49 0 举报
AI智能生成
Java并发编程
作者其他创作
大纲/内容
原子操作
原子整数
AtomicBoolean
AtomicInteger
AtomicLong
原子引用
AtomicReference
AtomicMarkableReference
AtomicStampedReference
原子数组
AtomicIntegerArray
AtomicLongArray
AtomicReferenceArray
字段更新器
AtomicReferenceFieldUpdater
AtomicIntegerFieldUpdater
AtomicLongFieldUpdater
原子累加器
LongAdder
Cell
@sun.misc.Contentd
防止 缓存行 伪共享
防止 缓存行 伪共享
longAccumulator
LongAccumulator
指令重排序
JVM能够根据处理器的特性(CPU的多级缓存系统、多核处理器等)适当的重新排序机器指令,使机器指令更符合CPU的执行特点,
最大限度的发挥机器的性能。
最大限度的发挥机器的性能。
CAS操作
Compare and Swap
Compare and Swap
CAS有3个操作数,内存值V,旧的预期值A,要修改的新值B。
当且仅当预期值A和内存值V相同时,将内存值V修改为B,否则什么都不做
当且仅当预期值A和内存值V相同时,将内存值V修改为B,否则什么都不做
Unsafe.compareAndSwapInt
非阻塞算法
(nonblocking algorithms)
(nonblocking algorithms)
一个线程的失败或者挂起不应该影响其他线程的失败或挂起的算法。
ABA问题
加版本号
AtomicStampedReference
一般CPU在进行线程的上下文切换的时间比执行CPU的指令集的时间长,所以CAS操作在性能上有很大的提升。
在执行CAS的操作中,没有更新成功的就会自旋,这样也会消耗CPU的资源,对于CPU来说是不友好的。
在执行CAS的操作中,没有更新成功的就会自旋,这样也会消耗CPU的资源,对于CPU来说是不友好的。
锁机制
synchronized
锁的是对象,不是代码
获取对象锁
同步代码块,锁是小括号()中的实例对象
同步非静态方法,锁是当前对象的实例对象
获取类锁
同步代码块(synchronized(类.class)),锁是类对象
同步静态方法
底层实现原理
对象头MarkWord
Java内部锁机制Monitor
字节码指令
monitorenter
monitorexit
同步方法 ACC_SYNCHRONIZED
Owner
锁池EntryList
等待池WaitSet
四种状态
锁膨胀方向:无锁 -> 偏向锁->轻量级锁->重量级锁
锁的内存语义
当线程释放锁时,Java内存模型会把该线程对应的本地内存中的共享变量刷新到主内存中
而当线程获取锁时,Java内存模型会把该线程对应的本地内存置为无效,从而使得被监视器保护的临界区代码必须从主内存中读取共享变量
而当线程获取锁时,Java内存模型会把该线程对应的本地内存置为无效,从而使得被监视器保护的临界区代码必须从主内存中读取共享变量
并发基石
AQS
AQS
volatile int state(代表共享资源)
FIFO线程等待队列(多线程争用资源被阻塞时会进入此队列)
LockSupport
阻塞线程:part()
唤醒线程:unpart(Thread thread)
两种资源
共享方式
共享方式
Exclusive(独占,
只有一个线程能执行,
如ReentrantLock)
只有一个线程能执行,
如ReentrantLock)
acquire()
独占模式下线程获取共享资源的顶层入口
独占模式下线程获取共享资源的顶层入口
release()
独占模式下线程获取共享资源的顶层入口
独占模式下线程获取共享资源的顶层入口
Share(共享,多个线程可同时执行,
如Semaphore/CountDownLatch)
如Semaphore/CountDownLatch)
acquireShared()
releaseShared()
Lock与ReentrantLock
加锁的原理(Lock.lock)
非公平锁NoFairLock
公平锁FairLock
锁释放(Lock.unLock)
条件变量(Condition)
高级功能
等待可中断
当持有锁的线程长期不释放锁的时候,正在等待的线程可以选择放弃等待
可实现公平锁
多个线程在等待同一个锁时,必须按照申请锁的时间顺序来依次获得锁
锁可以绑定多个条件
一个ReetrantLock对象可以同时绑定多个Condition对象
共享锁
CountDownLatch
闭锁,倒计时器
闭锁,倒计时器
countDown
await
CyclicBarrier
同步屏障
同步屏障
await
Semaphore
信号量
信号量
accquire()
acquire(int permits)
tryAcquire()
tryAcquire(int permits)
release()
release(int permits)
ReentrantReadWriteLock
读写锁
读写锁
StampedLock
新读写锁
新读写锁
子主题
Future
Callable
FatureTask
CompletableFuture
可以显式完成的Future(设置其值和状态),并且可以用作CompletionStage,支持在完成时触发依赖函数和操作
创建CompletableFuture
中间组合操作
转换
thenApply、thenApplyAsync
thenCombine
组合
thenCompose
消费
thenAccept、thenAcceptAsync
thenAcceptBoth
applyToEither
运行
thenRun、 thenRunAsync
批量
allOf
anyOf
终止
handle
whenComplete
exceptionally
通过阻塞或者轮询的方式获得结果
get
getNow
join
锁的一些其他问题
线程中断机制
Exchanger
线程池
线程
synchronized
对象锁
类锁
Thread中的start和run的区别
Thread和Callable的区别
sleep和wait的区别
notify和notifyAll的区别
yield
会给线程调度器一个当前线程愿意让出CPU使用的暗示,但是线程调度器可能会忽略这个暗示
线程池
作用
作用
减少资源消耗
通过复用池中已创建的线程,减少频繁创建、销毁线程带来的资源消耗
提高响应速度
当线程池中有空闲线程,任务到来时无需创建线程就能立即被执行
提高线程的可管理性
由线程池对池中的线程进行统一管理和监控,可防止无限制创建线程造成的资源浪费
Executor
ExecutorService
ExecutorService
ThreadPoolEcecutor
参
数
数
int corePoolSize
线程池核心线程数
int maximumPoolSize
池中的最大线程数
long keepAliveTime
当线程数大于corePoolSize时,多余空闲线程在终止之前等待新任务的最大时间
TimeUnit unit
keepAliveTime的时间单位
BlockingQueue<Runnable> workQueue
用于保存任务的队列,可以为无界、有界、同步移交类型的队列,这里是BlockingQueue。
当池子里的工作线程数大于corePoolSize时,这时新进来的任务才会放到阻塞队列中
当池子里的工作线程数大于corePoolSize时,这时新进来的任务才会放到阻塞队列中
ThreadFactory threadFactory
创建新线程的工厂类
RejectedExecutionHandler handler
队列已满且线程数达到maximunPoolSize时候的饱和策略,
取值有AbortPolicy、CallerRunsPolicy、DiscardOldestPolicy、DiscardPolicy;
取值有AbortPolicy、CallerRunsPolicy、DiscardOldestPolicy、DiscardPolicy;
缓冲
队列
队列
ArrayBlockingQueue
LinkedBlockingQueue
PriorityBlockingQueue
SynchronizedQueue
线程池任务拒绝策略
RejectedExecutionHandler
RejectedExecutionHandler
直接丢弃(DiscardPolicy)
丢弃队列中最老的任务(DiscardOldestPolicy)
抛异常(AbortPolicy)
将任务分给调用线程来执行(CallerRunsPolicy)
ScheduledThreadPoolExecutor
Timer
TimerTask
TimerTask
优点:简单易用
缺点:单线程串行执行
ScheduledFutureTask
DelayWrokQueue
带延迟的优先队列
带延迟的优先队列
delayedExecute
延迟执行任务
延迟执行任务
线程池的实现及原理
原子变量ctl
线程池状态
运行状态 RUNNING
关闭状态 SHOTDOWN
停止状态 STOP
整理状态 TIDYING
终止状态 TERMINATED
Worker
工作线程,继承了AQS
工作线程,继承了AQS
execute的执行过程
addWorker
工作线程的创建
工作线程的创建
runWorker
工作线程的执行
工作线程的执行
getTask
任务的获取
任务的获取
processWorkerExit
工作线程的退出
工作线程的退出
shutdown
线程池的终止
线程池的终止
Executors
线程池工具类
线程池工具类
newSingleThreadExecutor
newCachedThreadPool
newFixedThreadPool
newScheduledThreadPool
newSingleThreadScheduledExecutor
newWorkStealingPool
Fork/Join框架
三个
模块
模块
1、任务对象:ForkJoinTask
RecursiveTask:有返回值的任务
RecursiveAction:无返回值的任务
2、执行Fork/Join任务的线程:ForkJoinWorkerThread
3、线程池:ForkJoinPool
parallelStream
适用于CPU密集型任务,默认会创建与CPU核心数相同的线程数
工作窃取(work-stealing)
线程池大小配置
需根据任务类型来配置线程池大小
CPU密集型任务:CPU数目 + 1
IO密集型任务:最佳线程数目 = ((线程等待时间+线程CPU时间)/线程CPU时间 +1 )* CPU数目
通过Runtime.getRuntime().availableProcessors() 获得当前CUP个数
Executor生命周期
并发操作异常体系
并发总结
死锁
锁顺序死锁
动态的锁顺序死锁
资源死锁
死锁的四个必要条件
活跃度问题
饥饿
饥饿是指线程需要访问的资源被永久拒绝,以至于不能在继续进行
弱响应性
弱响应是指,线程最终能够得到有效的执行,只是等待的响应时间较长
活锁
活锁(Livelock)是指线程虽然没有被阻塞,但是由于某种条件不满足,一直尝试重试,却终是失败
常见的并发场景
常见的并发陷阱
性能与伸缩性
0 条评论
下一页