Java并发包
JDK核心库包
核心包是rt
其中java是JDK的公开api
javax是扩展的标准
com,sun中是基础实现
org集成第三方基础包
并发包java.util.concurrent(JUC)
atomic原子操作
locks锁 Lock本身 ReadWriteLock读写锁 Condition条件
什么是锁
为什么需要显示的Lock
synchronized 可以加锁,
wait/notify 可以看做加锁和解锁
为什么需要一个显示的锁
1.synchronized 块锁不灵活(灵活的锁是在什么条件下锁住什么条件下释放)
2 synchronized 锁住的时间,只有锁被占用就必须要等待
ReentrantLock重入锁 ,参数为true 为公平锁
重入锁 当第一次进来锁住,还没有释放,第二次来的时候可以再进去 不会卡住
公平锁,先来先进后来后进
可重入锁
第二次进入时是否阻塞
公平锁
–公平锁意味着排队靠前的优先
–非公平锁则是都是相同的机会
读写锁分开 读锁和写锁不会互相干扰
优化锁的两个基础原理
1 减少锁锁住的范围
2 锁分离,一把锁分多把锁
ReadWriteLock管理一组锁,一个读锁,一个写锁。
读锁可以在没有写锁的时候被多个线程同时持有,写锁独占。
所有读写锁的实现必须确保写操作对读操作的内存影响。每次只能有一个写线程,但是同时可以有多个线程并发的读数据。
ReadWriteLock适用于读多写少的并发情况
通过Lock.newCondition()创建
可以看作是Lock对象上的信号。类似于wait/notify
只要part了当前线程将就被锁住,需要被唤醒,但是当前线程暂停了,所以唤醒线程unpart必然实在其他线程中执行的
LockSupper类似于Thread类的静态方法,专门处理执行这个代码的线程
为什么unpart必须要一个线程参数
因为park线程,无法唤醒自己,只能由其他线程唤醒
最小使用锁
1,降低锁范围: 锁定代码的范围,作用域
2,细分锁粒度:将一个大锁,拆分成多个小锁
锁是局部的 不能暴露出去。
并发原子类java.util.atomic
并发的时候计数是不准的,封装的并发时候能够记准的东西
sum.incrementAndGet再并发时能够正确的加1
AtomucInteger中的volatile 的值每次操作都不会缓存,都是从主内存中取出来的真实的值
Unsafe包下的Compare-And-Swap 比较一下取到的值是否相同 相同可以set 不相同就set失败,返回值是boolean
例如银行取出5 现在花掉2元 ,5-2后将3再重新写入数据库。
悲观锁:取出5锁住,不让别人更新,当自己跟新完成后解锁selectforupdate
乐观锁:当发现数据库被改动,更新失败,更旧值作比较为乐观锁cas。可以通过乐观锁的自旋来比较最后插入
核心实现原理:
1volatile保证读写操作都可见(注意不保证原子性)
2使用CAS指定,作为乐观锁实现,通过自旋重试保证写入
一般来说不加锁快。
并发低的时候或者稍微高一点的是时候,无锁好
并发很高,有锁好
CAS本质上没有使用锁
并发压力跟锁性能的关系
1,压力非常小,性能本身要求就不高;
2,压力一般的情况下,无锁更快,大部分都一次写入;
3,压力非常大时,自旋导致重试过多,资源消耗很多;
LongAdder的改进思路
1,AtomicInteger和AtomicLong里的value是所有线程竞争读写的热点数据;
2,将单个value拆分成线程一样多的数据Cell[]
3,每个线程写自己的Cell[],最后对数据进行求个
并发工具类
复杂的应用场景如下
- 我们需要控制实际并发访问资源的并发数量
- 我们需要多个线程在某个时间同时运行
- 我们需要指定数量线程到达某个状态再继续处理
AQS
AbstractQueuedSychronizer,即队列同步器。他是构建锁或者其他同步组件的基础
(例如:Semaphore,CountDownLatch,ReentrantLock,ReentrantReadWriteLock)
是JUC并发包中的核心基础组件。
- AbstractQueuedSychronizer:抽象队列式同步器
- 两种资源共享方式:独占|共享,子类负责实现公平OR非公平
解决的问题
多线程抢占锁,怎样阻塞线程管理好,线程之间怎样共享状态和资源
资源本身的状态有两种
1 独占 如写操作
2 共享 如读操作
Semaphore - 信号量
信号量用来控制并发程序同时允许多少线程并发执行,相当于流控
CountdownLatch
可以看作式对线程的计数器,所有线程完成任务状态的聚合点
Master线程等待Worker线程把任务执行完
CyclicBarrier 屏障
和 CountdownLatch 相似 CyclicBarrier 是等待大家都变成某个状态
任务执行到一定阶段,等待其他任务对齐
CyclicBarrier 和 CountdownLatch的差别
CyclicBarrier 可以重复利用。
Future/FutureTask/CompletableFuture