( 만약 싱글코어 CPU 라면 ) 가시성 문제는 발생하지 않는다.
가시성 문제는 멀티스레드 환경에서 한 스레드가 값을 변경했을 때, 다른 스레드가 그 변경 사항을 즉시 확인하지 못하는 문제를 말합니다. 따라서 한 CPU의 캐시 메모리를 읽으면 발생하지 않는다.
그러나 동시성 문제는 발생할 수 있다. ( 동시성 문제는 값을 읽고 수정하는 작업이 중단 없이(원자적) 이루어지지 않을 때 발생합니다. )
또, 멀티 코어의 경우 각 코어가 독립적인 캐시 메모리를 가지기 때문에 가시성 문제가 발생할 수 있다.
CAS(Compare-And-Swap)란 : 동시성 문제를 해결하기 위한 비차단(Non-blocking) 알고리즘입니다. 락 없이 원자성을 보장하며, Atomic 클래스에서 이를 내부적으로 활용합니다.
CAS 동작 원리:
1. 메모리에서 현재 값(currentValue)를 읽음.
2. 기대 값(expectedValue)와 현재 값을 비교.
3. 같으면 새로운 값(newValue)으로 업데이트.
4. 다르면 실패하고 다시 시도.
장점: 락을 사용하지 않아 데드락(Deadlock)과 같은 문제가 발생하지 않음. 성능이 뛰어나며, 높은 동시성을 지원.
단점: ABA 문제: 값이 A → B → A로 변경되면, 이를 감지하지 못함.
참조(reference)와 함께 "스탬프(stamp)" 값을 원자적으로 관리하여, 참조 값이 중간에 변경되었다가 원래 값으로 돌아온 상황(ABA)을 감지할 수 있습니다.
스핀락(Spinlock): 반복적으로 실패 시 CPU 자원을 소모
synchronized가 적용되어 불필요한 락 경합이 발생.Concurrent 컬렉션 사용
Vector 대신 CopyOnWriteArrayList 사용Hashtable 대신 ConcurrentHashMap 사용Collections.synchronizedList 대신 병렬 처리에 적합한 컬렉션 사용락 범위 최소화
락 없는 알고리즘 활용
AtomicInteger, AtomicReference)를 활용하거나, 락 없는 자료구조를 사용합니다.| 항목 | Collections.synchronizedList | CopyOnWriteArrayList |
|---|---|---|
| 동기화 방식 | synchronized를 통해 전체 락 적용 | 쓰기 시 배열 복사, 읽기 작업은 락 없음 |
| 읽기 작업 성능 | 낮음: 락 획득 필요 | 높음: 락 없이 읽기 가능 |
| 쓰기 작업 성능 | 중간: 락 사용으로 제한적 | 낮음: 배열 복사로 메모리 사용량 증가 |
| 병렬 처리 성능 | 락 경합으로 인해 병렬 처리 성능이 낮음 | 읽기 작업에서는 높은 병렬 처리 성능 |
| 사용 환경 | 읽기/쓰기 작업이 모두 빈번한 환경 | 읽기 작업이 빈번하고 쓰기가 드문 환경 |
Collections.synchronizedListsynchronized 키워드를 사용하여 리스트 메서드를 동기화합니다.CopyOnWriteArrayListadd, remove, set)이 호출될 때마다 배열의 복사본을 생성하여 데이터를 수정합니다.Collections.synchronizedList가 적합한 경우CopyOnWriteArrayList가 적합한 경우put() 메서드 호출 시, 특정 키가 포함된 버킷에만 영향을 미칩니다.Collections.synchronizedMap() 메서드를 통해 동기화된 맵을 생성합니다.