JUC 并发类概览

JUC 并发类及并发相关类概览,持续补充...数组

  • AQS
    内部有两个队列,一个等待队列(先后节点),一个条件队列(后继节点),实际上是经过链表方式实现;
    等待队列是双向链表;条件队列是单向链表;条件队列若是被唤醒,将后接到等待队列上;
    经过内部持有的 state,加以模板模式,提供了两种资源争抢模式:排他、共享;而在争抢时,又辅以公平、非公平竞争的考虑;
    排他与共享分别经过子类实现的:boolean tryAcquire(tryAcquireShared(x) >= 0 来判断获取资源是否成功,同时排他限制:state 只能被一个线程修改(通常修改成 1,CAS(0,1),可重入);而共享则支持多线程同时更改 state 值(被多个线程获取);
    获取时要考虑是否关注中断唤醒行为,对应方法名后缀:-Interruptible,关注则抛异常,不关注则清除线程的中断标记位记录,继续挂起直到获取成功,再中断线程;
    总的下来,分支考虑就是:资源类型(是否排他)-> 是否公平 -> 是否关注中断(每个都是两个方向)
    释放资源时,排他类型须要判断是否当前线程,而共享类型不须要判断线程,只关注资源池;排他类型会唤醒等待队列的下一个节点,而共享则会经过级联方式传递信号,从 head 开始唤醒,直到资源被新唤醒的线程抢光才中止;
    线程的挂起是经过 LockSupport.park(thread),支持限时挂起;
    state 释放致使等待队列判断,进而唤醒。限时挂起一定支持中断响应;
    条件队列由于初始时是经过 new ConditionObject(),能够屡次建立,因此支持多个条件队列,使用同一个对象便是同一个条件队列;被唤醒时会执行 state 的资源获取,获取不到则进入等待队列;一样支持是否中断关注;而条件队列的中断有两种状况,一种在条件队列上被中断唤醒,一种是在进入等待队列后被中断唤醒;
    AQS 主要是资源 state 的 CAS 并发及线程中断挂起,排队的控制

  • AQLS
    state 的类型为 long,扩展了并发数(将来扩展)。其余与 AQS 相同。
    long 须要关注缓存行问题。

  • ReentrantLock
    基于 AQS 实现的锁,设置 state = 1;支持公平与非公平(判断队列是否有等待线程);支持重入,state 递增;竞争时只有 state = 0 才获取锁成功,不然进入等待队列;
    支持 condition 的 await 和 signal。

  • CopyOnWriteArrayList
    与 AQS 无关,使用的 synchronized 保证同步安全;当发生添加行为时,会将原数组拷贝一份进行添加,而后更新引用;当发生指定索引添加时,会定位索引,分两步进行拷贝(索引前、索引后);适合读多写少场景;addIfAbsent 会先判断(无同步锁),而后拷贝(有同步锁),判断时会先拷贝一份快照,在更新索引时判断快照是否最新,是则直接使用,不然从新拷贝;

  • CopyOnWriteArraySet
    底层使用了 CopyOnWriteArrayList。惟一性的添加则是使用了 addIfAbsent。其余大部分方法直接调用了 CopyOnWriteArrayList 的相似方法;

  • CountDownLatch
    使用了 AQS,初始化大小即为 state,每次 countDown 都是对 state - 1,而 await 则是在判断 getState() == 0 ? 1 : -1 不经过挂起在队列中,因此有多少 state 则其会被唤醒 state 次,而后从新挂起,直到 state = 0

  • ArrayBlockingQueue
    未直接使用或继承 AQS,而是经过使用 ReentrantLock 和 Condition 来完成多线程同步与挂起;
    内部使用数组存储元素,但不会扩展,实现了环形队列存储,队列元素增长 offer 及获取 poll 都使用 lock 进行同步;
    当添加成功时,进行 notEmpty.signal() 通知,唤醒获取失败的线程(notEmpty.await())处理;
    当获取成功时,进行 notFull.signal() 通知,唤添加失败的线程(notFulll.await())处理;
    offer(E) 添加返回 true/falseadd(E) 内部调用 offer,返回 false 则抛异常;put 自实现,没法添加则阻塞;
    poll() 获取返回 E/nulltake 自实现,若是获取不到则阻塞挂起;
    任何添加或获取成功,相应的都会进行 notEmptynotFull 通知,而失败则进入相反的队列挂起;ArrayBlockingQueue 的并发遍历实现是经过队列延展实现的(就是一个队列,不断的翻滚);相似于环形队列
相关文章
相关标签/搜索