JUC并发工具包之Phaser Part1 结构与状态

系列文章

JUC并发工具包之Phaser Part1 结构与状态
JUC并发工具包之Phaser Part2 源码分析
JUC并发工具包之Phaser Part3 场景使用
JUC并发工具包之Semaphore
JUC并发工具包之CyclicBarrier
JUC并发工具包之CountDownLatch
JUC并发工具包之CyclicBarrier & CountDownLatch的异同

预备知识

主要属性

// 状态变量,用于存储当前阶段phase、参与者数parties、未完成的参与者数unarrived_count
private volatile long state;
// 最多可以有多少个参与者,即每个阶段最多有多少个任务
private static final int  MAX_PARTIES     = 0xffff;
// 最多可以有多少阶段
private static final int  MAX_PHASE       = Integer.MAX_VALUE;
// 参与者数量的偏移量
private static final int  PARTIES_SHIFT   = 16;
// 当前阶段的偏移量
private static final int  PHASE_SHIFT     = 32;
// 未完成的参与者数的掩码,低16位
private static final int  UNARRIVED_MASK  = 0xffff;      // to mask ints
// 参与者数,中间16位
private static final long PARTIES_MASK    = 0xffff0000L; // to mask longs
// counts的掩码,counts等于参与者数和未完成的参与者数的'|'操作
private static final long COUNTS_MASK     = 0xffffffffL;
private static final long TERMINATION_BIT = 1L << 63;

// 一次一个参与者完成
private static final int  ONE_ARRIVAL     = 1;
// 增加减少参与者时使用
private static final int  ONE_PARTY       = 1 << PARTIES_SHIFT;
// 减少参与者时使用
private static final int  ONE_DEREGISTER  = ONE_ARRIVAL|ONE_PARTY;
// 没有参与者时使用
private static final int  EMPTY           = 1;

// 用于求未完成参与者数量
private static int unarrivedOf(long s) {
    int counts = (int)s;
    return (counts == EMPTY) ? 0 : (counts & UNARRIVED_MASK);
}
// 用于求参与者数量(中间16位),注意int的位置
private static int partiesOf(long s) {
    return (int)s >>> PARTIES_SHIFT;
}
// 用于求阶段数(高32位),注意int的位置
private static int phaseOf(long s) {
    return (int)(s >>> PHASE_SHIFT);
}
// 已完成参与者的数量
private static int arrivedOf(long s) {
    int counts = (int)s; // 低32位
    return (counts == EMPTY) ? 0 :
        (counts >>> PARTIES_SHIFT) - (counts & UNARRIVED_MASK);
}
// 用于存储已完成参与者所在的线程,根据当前阶段的奇偶性选择不同的队列
private final AtomicReference<QNode> evenQ;
private final AtomicReference<QNode> oddQ;

重要属性

state

状态变量,最高位存储当前phase是否被terminated,高31位存储当前阶段phase的值,中间16位存储parties的值,低16位存储unarrived的值
比如下面就是一个当前phase是1、parties是2、unarrived是1的状态值的二进制表示:

// 0,----------------- phase --------------, ----- parties -----, ---- unarrived ----
// 0,000 0000 0000 0000 0000 0000 0000 0001, 0000 0000 0000 0010, 0000 0000 0000 0001

evenQ & oddQ

已完成的参与者存储的队列,当最后一个参与者完成任务后唤醒队列中的参与者继续执行下一个阶段的任务,或者结束任务。

这两个Queue实现上没有区别,每个QNode保存一个waiter的信息。比如:

  • Thread引用
  • 阻塞的phase
  • 超时的deadline
  • 是否支持interrupted响应等

其中一个保存当前phase中正在使用的waiter,另一个备用。

当phase为奇数时使用evenQ、oddQ备用,偶数时相反。

当advance事件触发期间,新register的parties将会被放在备用的Queue中,advance只需要响应另一个Queue中的waiters即可,避免出现混乱。

一个内部类QNode

static final class QNode implements ForkJoinPool.ManagedBlocker {
    final Phaser phaser;
    final int phase;
    final boolean interruptible;
    final boolean timed;
    boolean wasInterrupted;
    long nanos;
    final long deadline;
    volatile Thread thread; // nulled to cancel wait
    QNode next;

    QNode(Phaser phaser, int phase, boolean interruptible,
          boolean timed, long nanos) {
        this.phaser = phaser;
        this.phase = phase;
        this.interruptible = interruptible;
        this.nanos = nanos;
        this.timed = timed;
        this.deadline = timed ? System.nanoTime() + nanos : 0L;
        thread = Thread.currentThread();
    }
}

先完成的参与者转换成节点放入队列中,这里我们只需要关注thread(它被volatile修饰,是核心值)和next两个属性即可,很明显这是一个单链表,存储着入队的线程。具体概念可查看预备知识里面的理解与使用Treiber Stack

位运算演算

使用到的变量

// 16位的整形最大值0000 0000 0000 0000 1111 1111 1111 1111
private static final int UNARRIVED_MASK = 0xffff; // to mask ints

状态的二进制位分布

// Primary state representation, holding four bit-fields:
//
// unarrived  -- the number of parties yet to hit barrier (bits  0-15)
// parties    -- the number of parties to wait            (bits 16-31)
// phase      -- the generation of the barrier            (bits 32-62)
// terminated -- set if barrier is terminated             (bit  63 / sign)

unarrived值的计算

// 求值过程
// 0,----------------- phase --------------, ----- parties -----, ---- unarrived ----
// 0,000 0000 0000 0000 0000 0000 0000 0001, 0000 0000 0000 0010, 0000 0000 0000 0001
//                                           0000 0000 0000 0010, 0000 0000 0000 0001 (cast to int)
//                                           0000 0000 0000 0000, 1111 1111 1111 1111 (& UNARRIVED_MASK)
//                                           0000 0000 0000 0000, 0000 0000 0000 0001 (得到低16位的unarrived值)
private static int unarrivedOf(long s) {
    int counts = (int) s;
    return (counts == EMPTY) ? 0 : (counts & UNARRIVED_MASK);
}

parties值的计算

// 求值过程
// 0,----------------- phase --------------, ----- parties -----, ---- unarrived ----
// 0,000 0000 0000 0000 0000 0000 0000 0001, 0000 0000 0000 0010, 0000 0000 0000 0001
//                                           0000 0000 0000 0010, 0000 0000 0000 0001 (cast to int)
//                                           0000 0000 0000 0000, 0000 0000 0000 0001 (无符号右移16位)
private static int partiesOf(long s) {
    return (int) s >>> PARTIES_SHIFT;
}

phase值的计算

// 求值过程
// 0,----------------- phase --------------, ----- parties -----, ---- unarrived ----
// 0,000 0000 0000 0000 0000 0000 0000 0001, 0000 0000 0000 0010, 0000 0000 0000 0001
// 0000 0000 0000 0000, 0000 0000 0000 0000, 0000 0000 0000 0000, 0000 0000 0000 0001 (无符号右移32位)
//                                           0000 0000 0000 0000, 0000 0000 0000 0001 (cast to int得到phase的值)
private static int phaseOf(long s) {
    return (int) (s >>> PHASE_SHIFT);
}

arrived值的计算

// 就是用parties的值减去unarrived的值
private static int arrivedOf(long s) {
    int counts = (int) s;
    return (counts == EMPTY) ? 0 :
            (counts >>> PARTIES_SHIFT) - (counts & UNARRIVED_MASK);
}

猜你喜欢

转载自blog.csdn.net/HalfImmortal/article/details/107169714