자바 동시성 프로그래밍 - 동기화 기법
모니터 (Monitor)
자바가 동기화를 지원하기 위해 사용하는 메커니즘은 모니터이며, 뮤텍스나 세마포어보다 더 고수준의 동기화 기법이다.
모든 자바 객체는 기본적으로 모니터를 가지며 여러 스레드가 객체의 임계 영역에 진입하려고 할 때 JVM은 모니터를 사용하여 스레드 간 동기화를 제공한다.
자바의 모니터는 상호 배제 및 협력 이라는 두 가지 동기화 기능을 제공하고 있으며 이를 위해 뮤텍스와 조건 변수를 사용한다.
상호 배제 (Mutual Exclusion)
객체가 가지고 있는 모니터 락을 통해 여러 스레드가 동시에 공유 자원에 접근하는 것을 막아 데이터의 일관성과 안전성을 보장하는 메커니즘이다.
JVM은
synchronized키워드를 이용하여 뮤텍스 동기화를 암묵적으로 처리해 주고 있으며synchronized는 메서드나 코드 블록에 적용할 수 있다.synchronized(동기화)
synchronized블록은 해당 객체의 모니터를 확득 할 수 있으며 모니터를 획득한 스레드만이 임계 영역에 접근 가능하고 그 외 다른 스레드들은 차단되어 대기 상태가 된다.synchronized블록을 빠져 나오면 모니터 락이 해제되고 대기 중인 다른 스레드 중 하나가 락을 얻어 임계 영역에 진입하여 작업을 수행하는 식으로 상호 배제가 보장된다.
협력 (Cooperation)
협력은 모니터의 조건 변수(Condition Variable) 를 통해 스레드 간 공동의 목표를 위해 상호 협력으로 데이터의 일관성과 안전성을 보장하는 동기화 메커니즘이다.
조건 변수(Condition Variable)
조건 변수는
Object클래스의 메서드인wait(),notify(),notifyAll()과 함께 작용하며 특정 조건이 만족될 때가지 스레드를 대기시키는 기능을 제공한다.스레드가 특정 조건에 부합하지 않을 때
wait()메서드를 호출하면 조건 변수의 대기 셋(Wait Set)에 들어가 대기한다.다른 스레드가 특정 조건을 만족해서
notify()또는notifyAll()메서드를 호출하면 해당 조건 변수의 대기 셋으로부터 스레드들을 깨워 실행시키게 된다.
조건 변수를 통해 스레드 간 대기와 통지를 서로 조잘하면서 경쟁 조건(Race Condition) 과 같은 문제를 방지할 수 있다.
모니터 내부에는 여러 개의 조건 변수를 가질 수 있지만 자바의 모니터에는 오직 한 개의 조건 변수만 가질 수 있다.
모니터 대기 셋 구조
자바의 모니터 내부에는
Entry Set(진입 셋)과Wait Set(대기 셋) 이라는 대기 자료 구조가 있으며 이들은 멀티 스레드 환경에서 스레드들 간의 상호 작용을 조절하는 데 사용된다.Entry Set
Entry Set은 모니터의 락을 획득하기 위해 대기 중인 스레드들을 모아 놓은 자료 구조로서, 스레드가 락을 사용 중인 경우 그 외 다른 스레드는Entry Set에 들어가게 된다.Entry Set에 있는 스레드들은 락이 반납될 때까지 기다리며 락이 반납되면Entry Set중 하나의 스레드가 락을 획득하고 임계 영역으로 진입하게 된다.
Wait Set
Wait Set은 모니터의 조건 변수와 함께 사용하는 자료 구조이며, 스레드들이 특정한 조건이 만족할 때까지 대기하고 있는 장소이다.스레드는
Wait Set에 들어가 대기할 때 락을 해제한다. 그리고 다른 스레드에 의해 깨어나게 되면Entry Set으로 이동해서 다시 락을 획득할 수 있다.

조건 변수 종류
조건 변수를 통해 상호 헙력하고 있는 두 스레드가
wait()과notify()메서드 실행 후에 하나의 모니터를 두고 두 스레드 모두 소유가 가능한 상황이 발생한다.하나는 대기 중인 스레드, 하나는 깨우는 스레드로서 어떤 스레드가 모니터를 먼저 소유할 것인가에 따라
Signal and Wait과Signal and Continue두 종류의 조건 변수로 나눌 수 있다.
Signal and Wait
현재 모니터를 소유하고 있는 스레드가
wait()을 실행하면 모니터 내부에서 자신을 일시 중단하고 락을 해제한 후Wait Set에 들어간다.깨우는 스레드가
notify()또는notifyAll()명령을 실행하면Wait Set에 있는 대기 스레드 중 하나 또는 모든 스레드를 깨우고, 깨우는 스레드는 락을 해제하고 대기한다.대기에서 깨어난 스레드가 락을 획득한 후 모든 작업을 마치고 락을 해제하면 깨운 스레드가 락을 획득한 후 계속 작업을 진행한다.
대기 스레드와 깨운 스레드 사이에 다른 스레드가 모니터를 소유할 수 없도록 원자적 실행이 보장되어야 한다.
Signal and Continue
현재 모니터를 소유하고 있는 스레드가
wait()을 실행하면 모니터 내부에서 자신을 일시 중단하고 락을 해제한 후Wait Set에 들어간다.깨우는 스레드가
notify()또는notifyAll()명령을 실행하면Wait Set에 있는 대기 스레드 중 하나 또는 모든 스레드를 깨운다. 이때 일어난 스레드들은Entry Set으로 이동한다.깨우는 스레드는 락을 계속 유지하면서 모든 작업을 완료하고 락을 해제하면
Entry Set에 대기하고 있는 모든 스레드가 락을 획득하기 위해 경쟁한다.자바에서는 이 조건 변수 형식을 취하고있다.
자바 모니터 작동 구조


Last updated