sychronized 란?
synchronized 는 자바에서 멀티스레드 환경에서 공유된 자원에 대한 동시 접근을 제어하기 위한 키워드이다.
synchronized을 이용하여 특정 블록 또는 메서드를 동기화 시켜 한 번에 하나의 스레드만 해당 블록 또는 메서드를 실행할 수 있다.
synchronized 를 사용하면 스레드들이 대기하고 경합하며, 이로 인해 성능 저하가 발생할 수 있다.
또한, 여러 스레드가 서로 락을 획득하고 기다리다가 데드락 상태에 발생할 수 있다.
서버 이중화시 동기화 문제점
만약 서버가 이중화 되어 있다면, 각 서버에서 별도의 자원을 가지게 됨으로, synchronized 문제가 발생할 가능성이 줄어들지만, 이중화된 서버들 사이에서 동기화된 자원을 공유하려면 동기화 문제가 발생할 수 있다.
즉, 각 서버의 각 스레드가 synchronized 에 동시 접근이 가능하다는 것이다.
즉, 서버 이중화 상태에서는 synchronized 이 동기화를 제대로 해결하지 못할 수도 있다.
여러 서버의 분산 락을 설정하고나, 분산 데이터베이스 또는 트랜잭션을 사용 등을 사용하여 해결할 수 있다.
AtomicXxx
Atomic 클래스는 synchronized, volatile 처럼 동기화를 보장해준다.
단일 서버 환경에서는 위 3개의 방식으로 동시성 문제 해결이 가능하다.
synchronized 키워드는 안전하게 동시성을 보장할 수 있지만, 비용이 크다.
volatile은 하나의 thread만 write 하고 나머지 스레드는 read만 한다는 전제하에 동시성을 보장한다 즉 Main Memory에서 read/write 작업이 직접 이뤄진다. 즉, 가시성 문제는 해결 가능하나, 동시 접근 문제는 해결할 수 없다.
Atomic 클래스는 CAS(Compare - And - Swap)를 이용하여 동시성 문제를 해결해, 여러 스레드에서 데이터를 write 해도 문제가 없다.
즉, synchronized 보다 적은 비용으로 동시성을 보장할 수 있다.
CAS 알고리즘이란 현재 스레드에 존재하는 CPU의 캐시와 메인 메모리에 저장된 값을 비교하여, 일치하는 경우 새로운 값으로 교체하고, 일치하지 않은 경우 기존 교체가 실패하게 되고, 이에 대해 계속 시도하는 방식이다.
CPU가 MainMemory의 자원을 CPU 캐시로 가져와 연산을 수행하는 동안, 다른 스레드에서 연산이 수행되어 MainMemory의 자원 값이 바뀌었을 경우, 기존 연산을 실패 처리하고, 새로 바뀐 MainMemory 값으로 재수행 한다.
CAS 알고리즘 진행 방식
- 인자로 기존 값(캐시에 저장된 값)과 변경할 값을 전달한다.
- 기존 값이 현재 메모리가 가지고 있는 값과 같다면, 변경할 값을 반영한다.
- 기존 값이 현재 메모리가 가지고 있는 값과 다르다면 값을 반영하지 않는다.
- CAS 알고리즘이 진행하는 동안 다른 스레드가 변수의 값을 변경하면, CAS 알고리즘은 실패하게 된다. 이 경우 CAS 알고리즘을 재 시도 해야 한다.
즉 Atomic 클래스는 synchronized와 다르게 non-blocking 하면서 원자성을 보장하여 동기화 문제를 해결한다.
'Back-end' 카테고리의 다른 글
가상 머신(스택 기반, 레지스터 기반) (0) | 2023.08.24 |
---|---|
Object.equals()를 재정의 해야 하는 이유 (0) | 2023.08.24 |
Servlet, ServletContainer vs DispatcherServlet (0) | 2023.08.24 |
volatile (0) | 2023.08.23 |
Thread(Java/OS) (0) | 2023.08.23 |