좌석 정보를 예로들어 살펴봅시다.
Thread1 고객1이 접근
1번 좌석 선택
정보 입력
결제 // 결제할 때 시간이 지연됨
Thread2 고객2가 접근
1번 좌석 선택
정보 입력
결제 // 고객1 보다 더 빠르게 결제 -> 고객2가 좌석 예약 성공
Thread가 공유자원을 사용하고 있기 때문에 해당 문제가 발생함
동기화를 통해서 해당 문제를 예방할 수 있음.
병렬처리 -> (동기화) -> 순차처리
Thread1 고객1
1번 좌석 선택
정보 입력
결제
해당 자원에 대한 권한을 Thread1에게 줌
Thread2 고객2
고객은 1번 좌석을 선택 하지 못하게 됨
하나의 Thread가 특정 작업을 마치기 전까지 다른 Thread에게 방해받지 않도록
처리하는 것을 말합니다.
공용 객체를 만들기 위해서 class로 정의 합니다.
예제
- 공용객체에 예금 금액 데이터가 들어가 있다고 가정합니다.
- 동일한 클래스에서 2개의 Thread를 만듭니다.(Thread class)
- 공용 객체에서 더이상 출금이 되지 않을 때 까지(0원이 될 때 까지) 예금을 인출
좌석정보라는 공유정보를 Thread가 함께 사용하고 있을 때를 가정합니다.
공유객체는 monitor라는 허가권을 가지고 있습니다.
monitor(Lock)은 이용권 같은 개념임.
Thread는 monitor를 획득함으로 써 정보에 접속할 수 있음 (Auth)
monitor를 획득하지 못한 Thread는 정보에 접속할 수 없음 (Blocked)
이런 방식으로 진행되면 자연스럽게 순차처리가 이루어짐
Thread가 공유객체를 오염시키는 것을 막는다.
synchronized
라는 키워드를 이용해서 monitor를 획득할 수 있습니다.
synchronized
앞에 붙이기public synchronized void withdraw(int money) {
// 코드
}
method 호출이 시작되면 lock(monitor)을 획득하고, lock(monitor)을 획득한 Thread만 공용객체에 접근하여 작업할 수 있게 됩니다.
synchronized block
을 사용합니다.동기화가 진행되는 영역을 말합니다.
public synchronized void withdraw(int money) {
// 코드
}
synchronized (this) {
// 해당 block안에서만 동기화가 실행됩니다.
}
임계영역 code가 다 실행되어야 다른 Thread가 실행될 수 있습니다.
현재 실행중인(Critical Section) Thread Lock을 놓고 wait상태로 전환.
해당 임계영역 실행 권한을 임의로 잠시 놓음 -> wait(대기)상태로 들어갑니다.
wait에 의해 일시 정지된 Thread중 하나의 Thread
에 대해 Runnable 상태로 전환시켜 줍니다.
notifyAll() 메서드
Object's wait pool blocked 상태에 있는 모든 Thread를
runnable 상태로 보내줍니다.