为什么推送ForkJoinPool.WorkQueue而不是使用array [index]需要Unsafe.putOrderedObject

时间:2018-03-29 03:05:35

标签: java java.util.concurrent unsafe forkjoinpool

    final void push(ForkJoinTask<?> task) {
        ForkJoinTask<?>[] a; ForkJoinPool p;
        int b = base, s = top, n;
        if ((a = array) != null) {    // ignore if queue removed
            int m = a.length - 1;     // fenced write for task visibility
            U.putOrderedObject(a, ((m & s) << ASHIFT) + ABASE, task);
            U.putOrderedInt(this, QTOP, s + 1);
            if ((n = s - b) <= 1) {
                if ((p = pool) != null)
                    p.signalWork(p.workQueues, this);
            }
            else if (n >= m)
                growArray();
        }
    }

U.putOrderedObject和U.putOrderedInt设置数组和WorkQueue的顶部。那么为什么不使用array [i] = task和top = s + 1.我正在阅读ForkJoinPool的源代码并解决这个问题。

来自oracle jdk 1.8(1.8.0_131)的源代码。

1 个答案:

答案 0 :(得分:0)

Unsafe在VarHandle之前处理了栅栏问题。有关详细信息,请参阅Rob Austin's blog。 F / J作者完成了书中的每一招,以加快速度。 VarHandle之前的代码最难理解,现在稍微不那么容易了。

他使用自己的原始数组,而不是使用标准Java数组(如ConcurrentLinkedQueue及其额外的开销)。