0
    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) 的源代码。

4

1 回答 1

1

Unsafe 在 VarHandle 之前处理了栅栏的问题。有关详细信息,请参阅Rob Austin 的博客。F/J 作者竭尽全力提高速度。VarHandle 之前的代码最难理解,现在更难理解了。

他没有使用标准的 Java 数组(比如 ConcurrentLinkedQueue 有额外的开销),而是使用了自己的原始数组。

于 2018-03-30T14:21:59.853 回答