DoubleAccumulator — 함수 기반 double 누적기

DoubleAccumulator — 함수 기반 double 누적기

DoubleAccumulator는 여러 변수를 함께 사용해 제공된 함수로 갱신되는 double 누적 값을 유지하는 클래스예요. 여러 스레드가 같은 값을 동시에 갱신할 때, 단일 AtomicLong처럼 한 곳만 두드리는 대신 필요에 따라 내부 변수를 늘려 경합(contention)을 줄이는 것이 핵심이에요.

출처: Java API Reference

본문

개념 이해하기

스레드 간에 accumulate(double) 업데이트가 경합하면, 경합을 줄이기 위해 변수 집합이 동적으로 늘어날 수 있어요. get()(또는 동등한 doubleValue())은 업데이트를 유지하는 변수들 전체에 걸친 현재 값을 반환해요.

이 클래스는 요약 통계처럼 자주 갱신되고 덜 자주 읽히는 공통 값을 여러 스레드가 업데이트할 때 대안보다 선호돼요.

제공하는 누적 함수는 부작용이 없어야 해요 — 스레드 경합으로 갱신이 실패하면 다시 적용될 수 있기 때문이에요. 예측 가능한 결과를 위해 누적 함수는 사용 맥락에서 요구되는 부동소수점 허용 오차 안에서 교환(commutative)이고 결합(associative) 이어야 해요. 함수는 기존 값(또는 항등원)을 한 인자로, 주어진 갱신 값을 다른 인자로 받아 적용돼요. 예를 들어 실행 최댓값을 유지하려면 항등원으로 Double.NEGATIVE_INFINITY와 함께 Double::max를 넘길 수 있어요.

스레드 내부/스레드 간 누적 순서는 보장되지 않아요. 따라서 수치적 안정성이 필요할 때, 특히 크기가 크게 다른 값들을 결합할 때는 이 클래스가 적합하지 않을 수 있어요.

public class DoubleAccumulator
extends Number
implements Serializable

합을 유지하는 흔한 특수 경우로는 DoubleAdder가 있어요. new DoubleAdder()new DoubleAccumulator((x, y) -> x + y, 0.0)과 동등해요.

이 클래스는 Number를 확장하지만 equals, hashCode, compareTo는 정의하지 않아요 — 인스턴스가 변경될 것으로 예상되므로 컬렉션 키로는 유용하지 않기 때문이에요.

생성자

public DoubleAccumulator(DoubleBinaryOperator accumulatorFunction, double identity)

주어진 누적 함수와 항등원을 사용해 새 인스턴스를 만들어요.

  • accumulatorFunction — 두 인자의 부작용 없는 함수
  • identity — 누적 함수의 항등원(초기 값)

누적·읽기

public void accumulate(double x)

주어진 값으로 갱신해요.

public double get()

현재 값을 반환해요. 원자적 스냅샷이 아니며, 동시 갱신이 없을 때만 정확해요. 값을 계산하는 동안 발생하는 동시 갱신은 반영되지 않을 수 있어요.

public void reset()

업데이트를 유지하는 변수들을 항등원 값으로 재설정해요. 새 업데이터를 만드는 대신 유용한 대안일 수 있지만, 동시 갱신이 없을 때만 효과가 있어요. 본질적으로 경쟁 조건(racy)이 있으므로, 동시에 갱신하는 스레드가 없다는 걸 알고 있을 때만 사용해야 해요.

public double getThenReset() — 효과상 get()을 호출한 뒤 reset()을 호출한 것과 같아요. 멀티스레드 계산 사이의 정지(quiescent) 지점에서 사용할 수 있어요. 이 메서드와 동시에 갱신이 있으면 반환값이 reset 직전의 최종 값임이 보장되지 않아요.

Number 변환

public double doubleValue()get()과 동등해요. (Number.doubleValue 구현)

public long longValue() — 좁히기 기본형 변환(narrowing primitive conversion) 후 long으로 반환해요.

public int intValue() — 좁히기 변환 후 int로 반환해요.

public float floatValue() — 좁히기 변환 후 float로 반환해요.

public String toString() — 현재 값의 문자열 표현을 반환해요. (Object.toString 오버라이드)

더 알아보기 (Learn more)