To Dare Is To Do!
자바의 동시성 이슈 (원자성 문제, atomic) 본문
이번 글에서는 지난 가시성의 문제와 volatile에 이어서 멀티 스레드 환경에서 발생할 수 있는 원자성의 문제에 대해 알아보려 한다.
원자성의 문제
원자성이란?
한 번에 하나의 단위 작업으로 간주되어야 하는 작업의 개념으로 여러 스레드가 동시에 공유자원에 접근할 때 더욱 고려되어야 하는 요소이다.
예를 들어 2개의 스레드가 동시에 count++ 연산을 100회 수행한다고 하자.
우리는 count의 값으로 200을 기대하지만 원자성이 보장되지 않는 상황에서는 결과가 우리의 예상과는 다르게 나온다.
원인을 찾아보면 count++ 연산은 READ - MODIFY - WRITE 3개의 instruction으로 구성된다.
만약 1번 스레드가 값을 읽어 count + 1을 하기 전에 2번 스레드가 count를 읽어 count + 1을 수행하고 반영했다면
1번 스레드의 작업 반영으로 인해 2번 스레드의 작업 결과는 무시될 것이다.
이러한 결과를 예방하기 위해 synchronized 혹은 atomic을 사용해야 한다.
synchronized와 atomic을 통해 원자성의 문제를 해결한다면 가시성의 문제도 해결할 수 있다.
synchronized 블럭에 들어가기 전에 CPU Cache Memory와 RAM을 동기화되며 atomic의 경우 CAS 알고리즘에 의해 원자성의 문제와 cache memory에 잘못된 값을 참조하는 문제를 해결해주기 때문이다.
+synchronized 키워드에 대한 정리
https://whitehartlane.tistory.com/30
synchronized
자바의 메모리 구조는 크게 method(static) 영역, stack 영역, heap 영역으로 구성되어 있다.https://whitehartlane.tistory.com/24 자바 메모리 구조 (feat 자바 변수)이전에 자바의 컴파일 과정에 대해 정리해본
whitehartlane.tistory.com
synchronized의 단점
synchronized는 멀티 스레드 환경에서 Blocking을 통해 공유객체를 동기화하는데 이런 방식은 성능 이슈를 초래할 수 있다.
만약 특정 스레드가 해당 블럭 전체에 lock을 걸면 해당 블럭에 접근하는 스레드들은 Blocking 상태에 들어간다.
Block 상태의 스레드들은 아무 작업도 하지 못한 상태로 일시 정지 상태가 되고, 다시 상태가 변경되는 동안 시스템의 자원을 사용하여 성능 저하의 원인을 야기시킬 수 있다.
atomic
멀티 스레드 환경에서 원자성을 보장하기 위해 나온 개념으로서 synchronized와 달리 non-blocking으로 원자성을 보장해 동기화 문제를 해결한다.
CAS (Compare And Swap) 알고리즘
CAS 알고리즘의 동작 원리
- 인자로 기존의 값 (Compared value)와 변경할 값(Exchanged value)을 전달
- 기존 값을 현재 메모리가 가지고 있는 값과 비교했을 때 같다면 변경할 값을 메모리에 반영시키고 true 반환
- 다르다면 반영하지 않고 false 반환
좀 더 자세하게 설명하면
1번 스레드가 공유자원에 대한 연산을 실행하고 메모리에 반영하기 직전 2번 스레드가 공유 자원의 값에 대한 연산을 마치고 먼저 메모리에 반영했다고 가정했을 때 1번 스레드가 연산을 수행하기 전 읽어왔던 값은 현재 메모리의 값과 다를 것이다. 이러한 경우 1번 메모리는 연산 결과를 메모리에 반영하지 않고 false를 반환하게 된다.
false가 반환되면 무한 루프가 구성되어 다른 스레드에 의해 변경된 메모리 값을 다시 읽고 연산을 수행하여 메모리의 값과 비교한 값으로 true가 반환될 때까지 작업을 반복한다.
이는 스레드의 상태를 변경하는 작업이 발생하지 않아 synchronized에 비해 상대적으로 성능이 우수하다.
📒정리
Atomic 변수의 핵심원리인 CAS 알고리즘 덕분에 원자성뿐만이 아니라 가시성의 문제까지 해결해 주는 것을 확인할 수 있다.
또한 기본적으로 non-blocking 방식으로 blocking 방식의 synchronized에 비해 성능적으로 이점이 있다는 것 또한 알 수 있다.
'Java' 카테고리의 다른 글
자바의 타입 (원시타입, 참조타입) (0) | 2024.07.24 |
---|---|
Checked Exception과 Unchecked Exception (0) | 2024.07.22 |
자바의 동시성 이슈 (가시성 문제, volatile) (0) | 2024.07.16 |
synchronized (0) | 2024.07.10 |
thread (0) | 2024.07.05 |