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的数组和顶部。那么为什么不直接使用arrayi=task和top=s+1呢?我正在阅读ForkJoinPool的源代码,并且遇到了这个问题。
来自oracle JDK1.8(1.8.0_131)的源代码。
发布于 2018-03-30 22:22:00
不安全在VarHandle之前就处理了栅栏的问题。有关详细信息,请参阅Rob Austin's blog。F/J的作者在这本书中使出了每一个技巧来提高速度。在VarHandle之前的代码是最难理解的,现在不那么难理解了。
他使用自己的原始数组,而不是使用标准的Java数组(像ConcurrentLinkedQueue这样会增加额外的开销)。
https://stackoverflow.com/questions/49547364
复制相似问题