앞에서 멀티쓰레드 환경에서 발생할 수 있는 문제상황들을 알아보았는데, 그렇다면 어떻게 해야 이런 문제상활들을 발생하지 않고 스레드 안전하게 할 수 있을까?
자바에서 활용할 수 있는 동기화 기법을 알아보자.
Synchroniztion 키워드 활용
synchroniztion 키워드를 활용하면, 여러 스레드에서 동시에 접근할 수 있는 객체에 Lock방식을 적용해서 하나의 스레드만 접근할 수 있도록 하는 것이다. 즉, 하나의 스레드가 Lock이 걸린 객체를 사용중이라면 다른 객체는 사용할 수 없게 막는 기법이다.
아래와 같이 메서드에 하나의 스레드만 접근하도록 막거나, 혹은 임계영역에만 적용시킬 수 도 있다.
// 하나의 스레드만 해당 메서드를 사용할 수 있다.
public synchronized void increment() {
...
}
// 메서드의 특정 영역에만 적용할 수 있다.
public void increment() {
synchronized (this.lock) {
count++;
}
}
원자적 연산
데이터 경쟁상태가 발생할 가능성이 있는지를 잘 확인해야 한다.
count++과같이 3개의 단계로 구성되어있는 연산 말고, 1개의 단계로 구성되는 원자적 연산만 사용한다면 데이터 경쟁상황이 발생하지 않을 것이다.
Java에서 원자적 연산에는 아래의 예시들이 존재한다.
// 1. 레퍼런스 참조
this.name = name
// 2. long, double을 제외한 모든 원시값 할당
long = 5L; // -> 원자성을 보장하지 못한다.(64bit로 인해 Java환경에서 보장해주지 못한다)
int = 5; // -> 원자성을 보자한다.
// 3. util.concurrent에서 제공하는 여러 원자적 단위의 API들
long, double타입은 원자적 연산이 되지 못한다고 하였지만, volatile 키워드를 사용하여 변수를 선언한다면 원자적 연산이 가능하도록 할 수 있다.
이렇게 사용하는 데이터나, 할당에 대해 원자적인지 아닌지 잘 판단할 수 있어야 할 것 같다.
세마포어
세마포어란 공유자원에 접근할 수 있는 스레드 수를 정해서 해당 수만큼의 스레드만이 공유 자원에 접근하도록 하는 것이다. Lock기법과는 다르게 정해진 숫자만큼의 스레드가 공유자원에 접근할 수 있도록 하는 방법이다.
주로 아래와 같이 생산자-소비자 패턴에서 사용된다.
Queue의 용량을 5로 정한다음에 들어가기 전에 acquire()를 통해 허가를 받고, release()를 통해 허가를 반납한다.
Semaphore full = new Semaphore(0);
Semaphore empty = new Semaphore(5);
Queue queue = new ArrayDeque();
Lock lock = new ReentrantLock();
// 스레드1. 생산자
while(true) {
Item item = produce();
empty.acquire();
lock.lock();
queue.offer(item);
lock.unlock();
full.release();
}
// 스레드2. 소비자
while(true) {
full.acquire();
lock.lock();
Item item = queue.poll();
lock.unlock();
consume(item);
empty.release();
}
* ReentarantLock : 자원점유의 공정성을 보장하고싶을 때 사용하는 용도의 Lock이다. 다른 스레드가 중단(대기상태)일 때 벗어날 수 있다.
<참고자료>
자바 병렬 프로그래밍 - https://product.kyobobook.co.kr/detail/S000000935083
'동시성 프로그래밍' 카테고리의 다른 글
모니터와 자바 동기화(synchronized) (0) | 2024.04.06 |
---|---|
[Java] 가상 스레드 (0) | 2024.01.11 |
[동시성 프로그래밍] 동기 vs 비동기 vs Blocking vs Non-blocking (0) | 2024.01.08 |
[자바 멀티쓰레드] CPU와 캐시메모리에 따른 데이터 문제 (0) | 2023.09.07 |
[자바 멀티쓰레드] 경쟁상태와 임계영역 (0) | 2023.09.07 |