DoubleAdder — 고성능 double 합계 계산기
DoubleAdder — 고성능 double 합계 계산기
DoubleAdder는 여러 변수를 함께 사용해 처음에 0인 double 합을 유지하는 클래스예요. 여러 스레드가 같은 합계를 동시에 갱신할 때 내부 변수를 동적으로 늘려 경합을 줄이고 성능을 높이는 데 초점을 맞춰요.
본문
개념 이해하기
add(double) 업데이트가 스레드 간에 경합하면 경합을 줄이기 위해 변수 집합이 동적으로 늘어날 수 있어요. sum()(또는 동등한 doubleValue())은 합을 유지하는 변수들 전체에 걸친 현재 총합을 반환해요.
스레드 내부/스레드 간 누적 순서는 보장되지 않아요. 따라서 수치적 안정성이 필요할 때, 특히 크기가 크게 다른 값들을 결합할 때는 이 클래스가 적합하지 않을 수 있어요.
이 클래스는 자주 갱신되고 덜 자주 읽히는 요약 통계 같은 공통 값을 여러 스레드가 갱신할 때 대안보다 선호돼요.
public class DoubleAdder
extends Number
implements Serializable
이 클래스는 Number를 확장하지만 equals, hashCode, compareTo는 정의하지 않아요 — 인스턴스가 변경될 것으로 예상되므로 컬렉션 키로는 유용하지 않기 때문이에요.
생성자
public DoubleAdder()
초기 합이 0인 새 adder를 만들어요.
합계 갱신·읽기
public void add(double x)
주어진 값을 더해요.
public double sum()
현재 합을 반환해요. 원자적 스냅샷이 아니며, 동시 갱신이 없을 때만 정확해요. 또한 부동소수점 연산은 엄밀히 결합적이지 않으므로, 단일 변수에 순차적으로 갱신한 값과 반환 결과가 반드시 동일한 건 아니에요.
public void reset()
합을 유지하는 변수들을 0으로 재설정해요. 새 adder를 만드는 대신 유용한 대안일 수 있지만, 동시 갱신이 없을 때만 효과가 있어요. 본질적으로 경쟁 조건(racy)이 있으므로, 동시에 갱신하는 스레드가 없다는 걸 알고 있을 때만 사용해야 해요.
public double sumThenReset() — 효과상 sum()을 호출한 뒤 reset()을 호출한 것과 같아요. 멀티스레드 계산 사이의 정지 지점에서 사용할 수 있어요. 이 메서드와 동시에 갱신이 있으면 반환 합이 reset 직전의 최종 값임이 보장되지 않아요.
Number 변환
public double doubleValue() — sum()과 동등해요. (Number.doubleValue 구현)
public long longValue() — 좁히기 기본형 변환 후 sum()을 long으로 반환해요.
public int intValue() — 좁히기 변환 후 sum()을 int로 반환해요.
public float floatValue() — 좁히기 변환 후 sum()을 float로 반환해요.
public String toString() — sum()의 문자열 표현을 반환해요. (Object.toString 오버라이드)