LongAccumulator — 함수 기반 long 누적기

LongAccumulator — 함수 기반 long 누적기

LongAccumulator는 여러 변수를 함께 사용해 제공된 함수로 갱신되는 long 누적 값을 유지하는 클래스예요. 여러 스레드가 같은 값을 동시에 갱신할 때 내부 변수를 늘려 경합을 줄이고 높은 처리량을 얻는 데 초점을 맞춰요.

출처: Java API Reference

본문

개념 이해하기

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

이 클래스는 통계 수집처럼 자주 갱신되는 공통 값을 여러 스레드가 갱신하되, 세밀한 동기화 제어가 필요하지 않을 때 AtomicLong보다 선호돼요. 갱신 경합이 낮을 때는 두 클래스가 비슷하지만, 높은 경합에서는 공간 소모가 커지는 대신 처리량이 훨씬 높아요.

스레드 내부/스레드 간 누적 순서는 보장되지 않으므로, 이 클래스는 누적 순서가 중요하지 않은 함수에만 적용할 수 있어요. 제공하는 누적 함수는 스레드 경합으로 갱신이 실패하면 재적용될 수 있어 부작용이 없어야 해요. 예측 가능한 결과를 위해 함수는 결합적이고 교환적이어야 해요. 예를 들어 실행 최댓값을 유지하려면 항등원으로 Long.MIN_VALUE와 함께 Long::max를 넘길 수 있어요.

public class LongAccumulator
extends Number
implements Serializable

카운트와 합을 유지하는 흔한 특수 경우로는 LongAdder가 있어요. new LongAdder()new LongAccumulator((x, y) -> x + y, 0L)과 동등해요.

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

생성자

public LongAccumulator(LongBinaryOperator accumulatorFunction, long identity)

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

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

누적·읽기

public void accumulate(long x)

주어진 값으로 갱신해요.

public long get()

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

public void reset()

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

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

Number 변환

public long longValue()get()과 동등해요. (Number.longValue 구현)

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

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

public double doubleValue() — 넓히기 변환 후 double로 반환해요.

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

더 알아보기 (Learn more)