모니터(Monitor)는 기존 mutex lock과 세마포어를 개선한 고급 동기화 기법이며, 상호 배제 및 실행 순서 제어를 위한 동기화를 지원합니다. 상호 배제는 mutex lock을 통해 지원합니다. 실행 순서 제어는 한 개 이상의 조건 변수(condition variable)를 통해 지원합니다.
모니터는 mutex lock을 사용하여 모니터 내부에서 하나의 프로세스만 실행될 수 있도록 합니다. Mutex lock은 sleep-and-wakeup 방식을 사용하며, 이를 지원하기 위해 entry queue가 존재합니다. 모니터는 entry queue를 사용해 lock을 획득하기 위해 대기하는 프로세스들을 관리합니다.
또한, 모니터는 한 개 이상의 조건 변수를 사용해 프로세스 간 실행 순서를 제어할 수 있습니다. 모니터의 각 조건 변수는 wait
과 signal
함수 및 waiting queue를 갖습니다. 조건 변수의 wait
함수를 호출한 프로세스들은 해당 조건 변수의 waiting queue에 들어가고, signal
함수를 호출한 프로세스는 해당 조건 변수의 waiting queue에서 대기 중인 프로세스를 깨워 실행될 수 있도록 합니다.
synchronized
자바의 synchronized
키워드는 모니터를 기반으로 동작합니다. 따라서 synchronized
키워드를 사용하면 mutex lock을 사용한 sleep-and-wait 방식의 상호 배제와 조건 변수를 사용한 실행 순서 동기화가 가능하며, 가시성 문제도 해결할 수 있습니다.
synchronized
키워드를 동기화가 필요한 메서드나 블럭에 사용해 해당 키워드를 사용한 메서드나 블럭을 한 번에 한 쓰레드씩만 실행하도록 보장할 수 있습니다. 자바의 모니터는 한 개의 조건 변수만 가지며, 실행 순서의 제어가 필요하다면 wait
과 notify
혹은 notifyAll
함수를 사용할 수 있습니다.
synchronized
키워드를 어디에 사용하느냐에 따라 lock으로 삼는 객체가 달라집니다. 같은 객체를 lock으로 삼는 쓰레드끼리만 동기화가 보장됩니다.
public class Counter {
private int count = 0;
private Object lock = new Object();
// synchronized 메서드
public synchronized void increment() {
count++;
}
public void decrement() {
// synchronized 블록
synchronized(lock) {
count--;
}
}
}
Note
동기화를 위해synchronized
나volatile
키워드를 직접 사용하는 것보다는java.util.concurrent
의 동시성 유틸리티를 사용하는 것을 권장합니다.