동시성 이슈 - 자바에서 동시성 이슈 해결
Index
1. 동시성 이슈란 무엇인가?
2. 자바에서 동시성 이슈 해결
3. 데이터베이스 동시성 제어
4. 분산 데이터베이스 동시성 제어
자바에서 동시성 이슈 해결
자바에서 하나의 프로세스는 메모리를 점유하고 있고, 그 프로세스 내의 여러 스레드가 자원을 공유한다.
공유되는 자원은 주로 힙 영역에 존재하는 객체와 static 변수 값이다.
public class Counter {
public int count = 0;
// 임계영역
public void increment(){
count++;
}
}
public class CounterTest {
public static void main(String[] args) {
Counter counter = new Counter();
Runnable task = () -> {
for (int i = 0; i < 10000; i++) {
counter.increment();
}
};
Thread thread1 = new Thread(task);
Thread thread2 = new Thread(task);
thread1.start();
thread2.start();
thread1.join();
thread2.join();
System.out.println("total count: " + counter.count);
}
}
위 코드의 기대 결과는 20000이나, 실제로는 20000보다 작은 값이 나올 수 있다.
이유는 두 스레드가 non-serial schedule 방식으로 겹쳐서 실행되기 때문이다.
현재 공유 자원에 동기화 없이 접근하고 있고, 하나의 스레드가 자원을 변경하므로 동시성 이슈가 발생할 수 있는 조건을 모두 충족한다.
해결방법
1. synchronized
public synchronized void increment(){
count++;
}
간단히 increment() 메서드에 synchronized 키워드를 추가하여 해결할 수 있다.
이 방식은 락을 획득하지 못한 다른 스레드를 대기 상태로 만들고, 실행 중인 스레드가 락을 반납할 때 대기 중인 스레드가 실행되도록 한다.
2. Atomic 연산
Atomic 연산은 CAS(Compare-And-Swap) 연산을 사용한다. CAS 연산을 통해 스레드는 직렬적(동기적)으로 처리된다.
하나의 스레드가 작업을 끝내면 다른 스레드가 실행되는 방식으로 동시성 문제를 해결한다.
3. Reentrant Lock
ReentrantLock도 비슷한 방식이지만, synchronized와 달리 대기 중인 스레드가 blocked 상태가 아닌 waiting 상태가 되어서
다른 스레드가 깨어나게 할 수 있다.
이로 인해 무한 대기 문제가 발생하지 않고, 특정 조건에 따라 스레드를 깰 수 있어 생산자-소비자 문제도 해결할 수 있다는 장점이 있다.
(2) 자바에서의 동시성 이슈 해결
자바에서의 동기화 기법 - 메모리 영역 자바에서 하나의 프로세스는 메모리를 점유하고 있으며, 그 프로세스 내의 여러 스레드가 자원을 공유하게 됩니다. 여기서 공유되는 자원은 주로 힙 영역
evoblog.life