学习笔记:《Offer来了(原理篇)》第3章 Java并发编程

重点词汇:
锁:synchronizedReentrantLock、Semaphore、Atomic原子类
关键字:volatile、CountDownLatch、CyclicBarrier

3.1 Java线程的创建方式

在这里插入图片描述

Thread类本身已经实现了Runnable接口。
Thread对象的run方法中其实调用了Runnable对象的run方法。

3.2 线程池的工作原理

3.2.1 线程复用

3.2.2 线程池的核心组件和核心类

核心组件:

  • 线程池管理器:用于创建并管理线程池。
  • 工作线程:线程池中执行具体任务的线程。
  • 任务队列:存放待处理的任务,新的任务将会不断被加入队列中,执行完成的任务将被从队列中移除。
  • 任务接口:用于定义工作线程的调度和执行策略,只有线程实现了该接口,线程中的任务才能够被线程池调度。

核心类:ThreadPoolExecutor、Executors、ExecutorService、Executor、Callable、Future、FutureTask

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

3.2.3 Java线程池的工作流程

在这里插入图片描述

3.2.4 线程池的拒绝策略

  • CallerRunsPolicy:调用者线程直接执行该线程任务。
  • DiscardPolicy:直接丢弃该线程任务。
  • DiscardOldestPolicy:丢弃最早的一个线程任务。
  • AbortPolicy:抛出异常。
  • 自定义拒绝策略

3.3 5种常用的线程池

在这里插入图片描述

3.4 线程的生命周期

在这里插入图片描述

在这里插入图片描述

3.5 线程的基本方法

  • 新建:new
  • 新建->就绪:start
  • 运行->就绪:yield
  • 运行->阻塞:sleep、suspend、wait、join
  • 阻塞->就绪:resume、notify、notifyAll
  • 运行->死亡:run、call、stop、interrupt、interrupted、isInterrupted、setDaemon
sleep()suspend()wait()
属于Thread类属于Thread类属于Object类
不释放锁不释放锁释放锁
到期自动恢复调用resume()恢复到期自动恢复;调用notify()/notifyAll()恢复
interruptisInterruptedinterrupted
添加中断标识查看中断标识查看中断标识并清除
操作调用方法的线程操作调用方法的线程操作当前代码所在的线程

3.7 线程上下文切换

  • 上下文:指线程切换时CPU寄存器和程序计数器所保存的当前线程的信息。
  • 上下文切换:CPU利用时间片轮询来为每个任务都服务一定的时间,然后把当前任务的状态保存下来,继续服务下一个任务。任务的状态保存及再加载就叫作线程的上下文切换。

在这里插入图片描述

3.12 Java中的线程调度

  • 抢占式调度:线程有同样的CPU时间片:一个线程的堵塞不会导致整个进程阻塞。
  • 协同式调度:线程自身控制CPU时间片:一个线程的堵塞将会导致整个进程阻塞。

3.13 进程调度算法

3.13.1 优先调度算法

  • 先来先服务调度算法
  • 短作业优先调度算法

3.13.2 高优先权优先调度算法

  • 非抢占式优先调度算法
  • 抢占式优先调度算法
  • 高响应比优先调度算法

响应比=(等待时间+服务时间)/服务时间

3.13.3 时间片的轮转调度算法

  • 时间片轮转调度算法
  • 多级反馈队列调度算法:流程如下

1、假设有N个队列(Q1,…,QN),优先级Priority(Q1) > … > Priority(QN)。也就是说,只有上一级队列为空时,才会调度下一级队列。
2、每级队列都分配时间片,优先级越低的队列分配的时间片越长。
3、除了优先级最低的队列,其余队列遵循的是先来先服务算法,如果在时间片内进程未结束则将进程存入下一级队列的末尾。对于优先级最低的队列,遵循时间片轮转调度算法,如果在时间片内进程未结束则将进程存入本级队列的末尾。

3.13.4 总结

非抢占式抢占式
非抢占式的高优先权优先抢占式的高优先权优先
短时间优先短剩余时间优先
先来先服务时间片轮转
高响应比优先多级反馈队列

3.14 什么是CAS

3.14.1 CAS的概念:比较并交换

CAS(Compare And Swap)指比较并交换。

CAS算法CAS(V,E,N)包含 3个参数,V表示要更新的变量,E表示预期的值,N表示新值。

在且仅在 V值等于 E值时,才会将V值设为 N;如果 V值和 E值不同,则说明已经有其他线程做了更新,当前线程什么都不做。最后,CAS返回当前V的真实值。

3.14.2 CAS的特性:乐观锁

在有多个线程同时使用CAS操作一个变量时,只有一个会胜出并成功更新,其余均会失败。失败的线程不会被挂起,仅被告知失败,并且允许再次尝试,当然,也允许失败的线程放弃操作。

3.14.3 CAS自旋等待

循环地进行CAS操作:失败则重试,成功则返回结果。

3.15 ABA问题

解决方法:使用版本号。

3.16 什么是AQS

AQS(Abstract Queued Synchronizer)是一个抽象的队列同步器,通过维护一个共享资源状态(Volatile Int State)和一个先进先出(FIFO)的线程等待队列来实现一个多线程访问共享资源的同步框架。

3.16.1 AQS的原理

在这里插入图片描述

3.16.2 state:同步状态

state的访问:getState()、setState()和compareAndSetState(),均是原子操作。

3.16.3 AQS共享资源的方式:独占式和共享式

自定义同步器的主要方法如下:

在这里插入图片描述

独占式:ReentrantLock

ReentrantLock对AQS的独占方式实现为:ReentrantLock中的state初始值为 0时表示无锁状态。在线程执行tryAcquire()获取该锁后ReentrantLock中的state+1,这时该线程独占ReentrantLock锁,其他线程在通过tryAcquire()获取锁时均会失败,直到该线程释放锁后state再次为 0,其他线程才有机会获取该锁。该线程在释放锁之前可以重复获取此锁,每获取一次便会执行一次state+1,因此ReentrantLock也属于可重入锁。但获取多少次锁就要释放多少次锁,这样才能保证state最终为 0。如果获取锁的次数多于释放锁的次数,则会出现该线程一直持有该锁的情况;如果获取锁的次数少于释放锁的次数,则运行中的程序会报锁异常。

共享式:CountDownLatch

CountDownLatch对AQS的共享方式实现为:CountDownLatch将任务分为 N个子线程去执行,将state也初始化为 N,N与线程的个数一致,N个子线程是并行执行的,每个子线程都在执行完成后countDown()一次,state会执行CAS操作并减 1。在所有子线程都执行完成(state=0)时会unpark()主线程,然后主线程会从await()返回,继续执行后续的动作。

3.6 Java中的锁

  • 乐观锁CAS、悲观锁AQS
  • 共享锁、独占锁
  • 读锁、写锁
  • 公平锁、非公平锁
  • 偏向锁->轻量级锁->重量级锁
  • 自旋锁
  • 可重入锁

重量级锁:大量线程竞争锁时,线程在就绪、运行、阻塞之间切换时,线程也会在用户态与内核态之间切换,开销大效率低。
轻量级锁:少量线程竞争锁时,使用自旋锁,线程不进入阻塞状态,直接等待持有锁的线程释放锁后获取锁,避免线程在用户态与内核态之间切换。
偏向锁:不存在锁竞争关系时,单一线程在使用重入锁的时候,消除锁重入的造成开销,只执行一次CAS原子操作。

3.6.1 synchronized

悲观锁、独占锁、非公平锁、重量级锁、自旋锁、可重入锁

内部区域:ContentionList、EntryList、Ondeck、Owner、!Owner、WaitSet

在这里插入图片描述

3.6.2 ReentrantLock

lock()、unLock()

悲观锁、独占锁、读锁/写锁、公平锁/非公平锁、自旋锁、可重入锁

避免死锁:轮询锁、定时锁、中断锁

3.6.3 Semaphore

acquire()、release()

悲观锁、公平锁/非公平锁

避免死锁:轮询锁、定时锁、中断锁

3.6.4 Atomic原子类

  • 原子普通类:AtomicBoolean、AtomicInteger、AtomicLong、AtomicReference
  • 原子数组类:AtomicIntegerArray、AtomicLongArray、AtomicReferenceArray
  • 原子字段更新器:AtomicIntegerFieldUpdater、AtomicLongFieldUpdater、AtomicReferenceFieldUpdater
  • 带版本号的原子引用类:AtomicStampedReference、AtomicMarkableReference
  • 原子累加器:LongAdder、LongAccumulator、DoubleAdder、DoubleAccumulator、Striped64

3.6.17 如何进行锁优化

  • 去掉不必要的锁
  • 精简锁持有的时间
  • 粗化或细化锁的粒度
  • 按功能分离锁(读写锁)

3.9 Java并发关键字

  • CountDownLatch:计数器、不可重用。latch.await()、latch.countDown()。
  • CyclicBarrier:循环屏障、可重用。cyclicBarrier.await()、cyclicBarrier.await(long timeout, TimeUnit unit)。
  • volatile:volatile变量。因为使用该修饰符并不能帮助实现原子性,所以使用时需要满足两个条件:写操作不依赖于当前值;写操作不依赖于其他被volatile修饰的值。

在这里插入图片描述

在这里插入图片描述

3.10 多线程如何共享数据

可见性有序性原子性
synchronized
volatile×

3.8 Java阻塞队列

略。

3.11 ConcurrentHashMap并发

略。

串联记忆

在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值