반응형
AtomicInteger.class
Java에서 사용하는 클래스로 멀티 스레드 환경에서 안전하게 사용되기 위한 원자성을 보장받는 자료형이다
클래스의 주요 기능 및 특징
- 원자적 연산
- 다른 스레드가 해당 연산의 중간 상태를 볼 수 없음
- 스레드 안전
- 여러 스레드에서 동시에 접근하더라도 데이터 경합 없이 안전하게 값을 읽고 쓸 수 있음
- 락 없이 동작
- 기존의 동기화 방식(synchronized 키워드)은 락을 사용하지만, 아토믹 연산은 CPU가 제공하는 하드웨어 수준의 락-프리(Lock-Free) 매커니즘을 사용
- CAS 알고리즘
내부적으로 CAS(Compare-And-Swap) 알고리즘을 사용하여 값을 업데이트- 특정 메모리 위치 값이 예상값과 같은지 확인한 후, 같다면 새 값으로 교체
- 이 과정에서 충돌을 감지
주요 메서드
- get()
- set(int newValue)
- getAndIncrement()
- 현재 값 반환 후 1 증가
- incrementAndGet()
- 값을 1 증가시키고 증가된 값 반환
- compareAndSet(int expect, int update)
- 현재 값이 expect와 같으면 update 값으로 변경 (CAS 연산)
사용 고려 시점
- 동시성 프로그래밍에서 데이터를 안전하게 업데이트해야 하는 경우
- 멀티 스레드 환경에서 카운터 증가
- 통계 집계
- 락 기반 동기화보다 가벼운 대안
- 성능이 중요한 환경에서 데이터 무결성을 유지해야 할 때
❓CAS (Compare-And-Swap)
CAS는 값의 업데이트가 특정 조건에서만 이루어지도록 보장하는 하드웨어 지원 원자적 연산
따라서 자바에만 있는 것이 아니라, C 계열의 언어에서도 std::atmoic 클래스와 같이 사용되고 있음
CAS 작동 방식
- 특정 메모리 위치에 대해, 세 값을 비교 및 업데이트
- 현재 값 (current): 현재 메모리에 저장된 값
- 기대 값 (expected): 우리가 예상하는 값
- 새 값 (new): 우리가 저장하려는 값
- CAS 연산의 과정
- 메모리의 현재 값이 기대 값(expected)과 동일하면, 새 값으로 업데이트
- 메모리의 현재 값이 기대 값과 다르면 실패를 반환
CAS 장점
- 스케일링 가능성: 여러 스레드가 동시에 접근해도 성능 저하가 적다.
- 스레드가 블로킹되지 않으므로 데드락 위험성이 없다
CAS 단점
- Busy-waiting:
- 실패할 경우 재시도하는 루프를 사용하므로 CPU 자원을 소비할 수 있다.
- 특히 충돌이 빈번하면 성능 저하가 발생할 수 있다.
- ABA 문제:
- 메모리 값이
A -> B -> A
로 변경된 경우, CAS는 값이 바뀌지 않았다고 판단할 수 있다. - 이 문제는 태그(tag) 또는 버전 관리를 통해 해결
- 메모리 값이
코드 예시 - 과정만 참고
public final int incrementAndGet() {
for (;;) {
int current = get(); // 현재 값 읽기
int next = current + 1; // 새로운 값 계산
if (compareAndSet(current, next)) // CAS 연산
return next; // 성공 시 반환
}
}
CPU의 원자적 명령어
CPU는 CAS 연산을 지원하기 위해 특정 명령어(기계어)를 제공
- x86 아키텍처 - CMPXCHG(Compare and Exchange)
- ARM 아키텍처 - LDREX/STREX
메모리 값을 읽고 수정하는 작업을 한 번에 처리하므로, synchronized 키워드 없이 안전하게 업데이트
반응형
'호기심 천국 > Java' 카테고리의 다른 글
멀티스레드 문제 상황 예시 1 (1) | 2025.01.20 |
---|---|
StringBuilder vs String 문자열합치기 (0) | 2023.09.19 |