AQS并发框架介绍

AQS并发框架介绍

一、jdk高级并发组件介绍

1、CyclicBarrier

协调多线程阻塞在某个屏障点,并在指定数量线程全达到屏障点后同时解除阻塞。(面包车的例子)

可以循环使用

使用lock.condition实现

如何使用:

Await 当我们拿到1CyclicBarrier实例时,如果调用await(),它的线程到达这个障碍点。CyclicBarrier(int parties) 指定达到的数量,线程过来调用await()方法,直到线程数量达到parties,解除阻塞。

1、CountdownLatch

使用场景:使线程阻塞直到指定数量的操作完成。(红绿灯的例子)

使用AQS实现

不可循环使用

CountdownLatch使用:

CountdownLatchint count;过来一个线程调用await()方法;

countDown() 倒数,减一逐渐减为0,减为0后,之前调用await()的线程全部解除阻塞。CountdownLatch和线程数没有关系

 

如果countDown()变为0后,后续的线程如果再调用await方法直接通过。这也是和CyclicBarrier的不同点。

1、总结:CountdownLatchCyclicBarrier有什么不同?

CountdownLatch不可循环使用

CountdownLatch:任意多个线程阻塞直到其它线程countDown()为0为止;CyclicBarrier,线程数量达到指定数量解除阻塞

CyclicBarrier使用lock.condition实现,CountdownLatch使用AQS实现。

利用CountdownLatchCyclicBarrier模拟高并发

 

1、Semaphore

使用场景:控制并发资源数量(停车场例子)

不可重入

支持公平和非公平

Sempahore如果传1就类似于lock

信号量为1Sempahorelock的区别:

Sempahore不可重入;

②要求拥有锁的人进行释放,而Sempahore不要求持有线程才释放

API:

① acquire() 获得锁

② Release()释放锁   构造函数Sempahoreint permits

 

 

1、ReentrantLock

使用场景:严格互斥,同一时间只允许一个线程访问,只有当前线程允许释放。

支持公平和非公平

一、AbstractQueuedSynchronizerAQS

1、并发组件的共性

① 阻塞 唤醒

② 阻塞和唤醒的逻辑

③ 公平和非公平:阻塞时可能需要排队

2、基于AQS实现的并发类

Semaphore

CountdownLatch

ReentratnLock

ReentratnReadWriteLock

worker

3、AQS基石

1)阻塞和唤醒:LockSupport.park  unpark

• 底层使用pthread_cond_timedwait & pthread_cond_signal

2)Permit logic : int state

并发中的if then问题

3)Atomic update :Unsafe.compareAndSwapXX() CAS

底层使用 cmpxchg

4) Fair & unFair: CLH queue

5) CAS

API:compareAndSetXX(field,expect,new)

自旋乐观锁,尝试一下,如果不成再试一次。

Linux底层实现:

Lock cmpxchg

注意,cmpxchg本身非原子性,多核需要加lock辅助

6LockSupport.park await的区别

park是不含任何业务逻辑,是无条件的,await()等待,要求别人通知我,蕴涵了业务逻辑的概念。

4AQS CLH QUEUE

一个双线链表(不用考虑扩容,性能高)

Head不含重要语义,其它队列里存的是等待的线程。

 

在没有高级同步API帮助下,如何保证同步安全操作?

For +CAS

②每个节点对应一个线程

WaitStatus:该节点等待状态,用CAS修改。

10

2)signal:后一个node将会block,当前节点relase/cancel时,需要unpark后一个节点。(需要把信息给别人)

3)CANCELLED:timeout/interrupt

4)CONDITION:

5)PROPAGATE:share模式下使用,因为可能需要release多个后续节点

Dummy header -  header 对应的节点为非阻塞

1、AQS API

1)AQS使用模板模式

acquire

release

acquireShared

releaseShared

2)子类需要实现的API(根据shared/exclusive选其一)

tryAcquire

tryRelease

tryAcquireShared

tryReleaseShared

2、AQS核心API

acquire: tryAcquire(), 如果失败则入queue, 自旋park,成功则更新

head。

• release: tryRelease(), 如果成功(一般都成功), unpark后继节点

• acquireShared: tryAcquireShared() , 如果失败入queue,自旋park。

• releaseShared:如果成功(一般都成功), 级联unpark后继节点。

• 所以exclusive shared模式最大的不同就是shared模式下,可能需要unpark后续n个节点而exclusive只用一个。

3、AcquireShared

首先入队,一直处于循环状态,

 

 

 

 

 

1、AQS template pattern

创建1AQS子类,一般起名为sync

根据是shared还是exclusive选择实现sync中对应API

根据业务逻辑选择当前并发工具类的API对应的syncAPI

2、ReentrantLock实现

1State :

0 无锁

1 有锁

2)可重入控制

exclusiveOwnerThread

3)公平和非公平锁

公平

非公平:只体现在第一次上面

4Condition

condition使用另一个 queue:condition queue

Await:将节点加入到condition queue park

Signal/signalAll:将节点从condition queue 移动到 sys Queue

await() 把锁放掉

 

 

问题:下面这段代码,调用singal()时,T1会不会执行wait()下面的方法?

不会,因为singal(),只是把队列放到了 sys Queue里面,只有执行了unlock()方法,当T1获得锁后,开始执行。

 

 

调用condition.wait() 和。Signal()之前,为什么要加lock()

If  then时,容易发生并发,其它线程修改其状态,导致永远不能唤醒

总结:统一理解

AQS 使用clh队列支持公平性

AQS 使用park/unpark来阻塞/唤醒线程

AQS 使用state字段管理阻塞逻辑

 

 

 

 

 

 

 

posted @ 2021-04-14 17:23  majingyun  阅读(131)  评论(0编辑  收藏  举报