Почему он использует pending и PENDING?
Первое - это поле, второе - его дескриптор для выполнения операций atomi c над полем.
почему бы просто не использовать что-то вроде AtomicInteger?
Они могли бы. Я подозреваю, что это просто производительность. Большинство частей API параллелизма сильно оптимизированы, так как с большой вероятностью они будут задействованы в узких циклах.
AtomicInteger
под капотом делает в основном те же вещи, что и здесь, для обеспечения операций atomi c, поэтому его использование было бы одним из уровней косвенного обращения к вызовам методов, которое является избыточным с небольшим количеством копипаста. Абсолютно крошечный прирост производительности, да, но для некоторых специализированных приложений это того стоит.
Да, было бы проще повторно использовать AtomicInteger
, но цели API параллелизма отличаются от те из ваших или моих проектов. Производительность - приоритет №1, а все остальное вторично.
Почему иногда используется pending
, например, в setPendingCount()
, а иногда PENDING
Он использует volatile поле непосредственно для операций, которые уже являются atomi c. setPendingCount
просто назначает поле
public final void setPendingCount(int count) {
pending = count;
}
В других случаях, когда требуется сравнение и установка, необходимо функционировать как операции atomi c, а VarHandle
обеспечивает эту функциональность
public final boolean compareAndSetPendingCount(int expected, int count) {
return PENDING.compareAndSet(this, expected, count);
}
И даже использует оба, например, в decrementPendingCountUnlessZero()
Опять же, ответ - атомарность. То, как они написали это в этом методе, - наиболее эффективный способ добиться атомарности для этой функции.