자바의 정석 - 쓰레드 4

송용준·2023년 5월 24일

쓰레드의 동기화(synchronization)

  • 멀티 쓰레드 프로세스에서는 다른 쓰레드의 작업에 영향을 미칠 수 있다.
  • 진행중인 작업이 다른 쓰레드에게 간섭받지 않게 하려면 '동기화'가 필요
  • 동기화 하려면 간섭받지 않아야 하는 문장들을 '임계 영역'으로 설정
  • 임계영역은 락(자물쇠)을 얻은 단 하나의 쓰레드만 출입가능(객체 1개에 락 1개)

synchronized를 이용한 동기화

  • synchronized로 임계영역(lock이 걸리는 영역)을 설정하는 방법 2가지

    임계영역을 자물쇠로 잠궈버리면 다른 쓰레드가 들어오지 못한다.
    synchronized를 이용하면 임계영역이 끝나기 전까지 다른 쓰레드로 작업하지 않는다.

wait() 과 notify()

  • 동기화의 효율을 높이기 위해 wait(), notify()를 사용.
  • Object클래스에 정의되어 있으며, 동기화 블록 내에서만 사용할 수 있다.
    - wait() : 객체의 lock을 풀고 쓰레드를 해당 객체의 waitting pool에 넣는다.
    - notify() : waiting pool에서 대기중인 쓰레드 중의 하나를 깨운다.
    - notifyAll() : waiting pool에서 대기중인 모든 쓰레드를 깨운다.

wait()과 notify() - 예제1

  • 요리사는 Table에 음식을 추가. 손님은 Table의 음식을 소비
  • 요리사와 손님이 같은 객체(Table)을 공유하므로 동기화가 필요

예외 1. 요리사가 Table에 요리를 추가하는 과정에 손님이 요리를 먹음

에외 2. 하나 남은 요리를 손님 2가 먹으로 하는데, 손님 1이 먹음

< 동기화 >
문제점 1. : Table을 여러 쓰레드가 공유하기 때문에 작업 중에 끼어들기 발생
해결책 1. : Table의 add()와 remove()를 synchronized로 동기화

< wait()와 notify >
문제점 2. : 예외는 발생하지 않지만, 손님이(CUST2)이 Table에 lock건 상태를 지속
요리사가 Table의 lock을 얻을 수 없어서 음식을 추가하지 못함
해결책 2. : 음식이 없을 때, wait()으로 손님이 lock을 풀고 기다리게 하자.
요리사가 음식을 추가하면, notify()로 손님에게 알리자(손님이 lock을 재획득)

테이블에 음식이 없어서 손님이 대기할 수도 있고, 테이블에 음식이 가득차서 요리사가 대기할 수도 있다.
요리사 : 테이블이 가득차면 대기(wait())하고, 음식을 추가하고 나면 손님에게 통보(notify())한다.
손님 : 은식이 없으면 대기(wait())하고, 음식을 먹고 나면 요리사에게 통보(notify()) 한다.
wait() 할 때는 lock을 푼다.

profile
용용

0개의 댓글