CountedCompleter类中的“私有静态最终VarHandle挂起”有什么作用

仙人掌

我正在阅读CountedCompleterJDK9中的源代码,这是与我的问题相关的代码:

public abstract class CountedCompleter<T> extends ForkJoinTask<T> {
    /** The number of pending tasks until completion */
    volatile int pending;

    // VarHandle mechanics
    private static final VarHandle PENDING;
    static {
        try {
            MethodHandles.Lookup l = MethodHandles.lookup();
            PENDING = l.findVarHandle(CountedCompleter.class, "pending", int.class);

        } catch (ReflectiveOperationException e) {
            throw new ExceptionInInitializerError(e);
        }
    }

    /**
     * Sets the pending count to the given value.
     *
     * @param count the count
     */
    public final void setPendingCount(int count) {
        pending = count;
    }

    /**
     * Adds (atomically) the given value to the pending count.
     *
     * @param delta the value to add
     */
    public final void addToPendingCount(int delta) {
        PENDING.getAndAdd(this, delta);
    }

    /**
     * If the pending count is nonzero, (atomically) decrements it.
     *
     * @return the initial (undecremented) pending count holding on entry
     * to this method
     */
    public final int decrementPendingCountUnlessZero() {
        int c;
        do {} while ((c = pending) != 0 &&
                     !PENDING.weakCompareAndSet(this, c, c - 1));
        return c;
    }
}

这是我的问题:

  1. 为什么使用未决和PENDING为什么不只使用类似的东西AtomicInteger
  2. 为什么有时它使用之前,例如在setPendingCount(),但有时使用PENDING,例如在addToPendingCount()它甚至使用了两者,例如decrementPendingCountUnlessZero()
迈克尔:

为什么使用挂起和挂起?

前者是场,后者是它的句柄,用于对场执行原子操作。

为什么不只使用AtomicInteger之类的东西呢?

他们可以。我怀疑这只是表演。并发API的大多数部分都经过了高度优化,因为它们很可能涉及紧密循环。

AtomicInteger在底层执行与确保原子操作基本相同的操作,因此使用它将是方法调用的一种间接级别,仅使用少量复制粘贴即可实现此目的。是的,性能提升绝对是很小的,但是对于某些专业应用程序来说,这将是值得的。

是的,重用代码会更简洁AtomicInteger,但是并发API中的目标与您或我的项目的目标不同。性能是第一要务,其他都是次要的。

为什么有时使用pending,例如在中setPendingCount(),但有时使用PENDING

它直接将volatile字段用于已经是原子的操作。setPendingCount只是分配给领域

public final void setPendingCount(int count) {
    pending = count;
}

其他需要比较和设置的情况需要充当原子操作,并VarHandle提供该功能

public final boolean compareAndSetPendingCount(int expected, int count) {
    return PENDING.compareAndSet(this, expected, count);
}

它甚至使用了两者,例如 decrementPendingCountUnlessZero()

同样,答案是原子性。他们用这种方法编写的方式是实现该功能原子性的最高效方式。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章