- 멀티 쓰레드 프로세스에서는 다른 쓰레드의 작업에 영향을 미칠 수 있다.
- 진행중인 작업이 다른 쓰레드에게 간섭받지 않게 하려면 '동기화'가 필요
- 쓰레드의 동기화 - 한 쓰레드가 진행중인 작업을 다른 쓰레드가 간섭하지 못하게 막는 것
- 동기화하려면 간섭받지 않아야 하는 문장들을 '임계 영역'으로 설정
- 임계영역은 락(lock)을 얻은 단 하나의 쓰레드만 출입가능(객체 1개에 락 1개)
- synchronized로 임계영역(lock이 걸리는 영역)을 설정하는 방법 2가지
- 메서드 전체를 임계 영역으로 지정 = 1번에 1쓰레드로 최소화한다.
- 특정한 영역을 임계 영역으로 지정 = 객체의 참조변수 뒤에 괄호를 넣어 지정한다.
- 동기화에서는 private를 사용해야 의미가 있다.
- 출금 쓰레드를 동기화
- acc.withdraw = 출금 쓰레드를 호출해서 잔고를 불러온다.
- synchroinzed가 없으면 음수가 나오게 된다. (if문을 통과하므로)
- 그래서 A라는 쓰레드가 임계영역 안에 있으므로 자물쇠를 가지고 들어오게 되고, 다른 쓰레드가 들어오지 못하게 된다. 임계영역을 벗어나면 자물쇠를 반납한다.(= 임계영역 안에서는 하나의 쓰레드만 들어오게 된다.)
- synchroinzed가 붙으면 음수가 나오지 않는다# ch 13-30~33 쓰레드의 동기화
- 멀티 쓰레드 프로세스에서는 다른 쓰레드의 작업에 영향을 미칠 수 있다.
- 진행중인 작업이 다른 쓰레드에게 간섭받지 않게 하려면 '동기화'가 필요
- 쓰레드의 동기화 - 한 쓰레드가 진행중인 작업을 다른 쓰레드가 간섭하지 못하게 막는 것
- 동기화하려면 간섭받지 않아야 하는 문장들을 '임계 영역'으로 설정
- 임계영역은 락(lock)을 얻은 단 하나의 쓰레드만 출입가능(객체 1개에 락 1개)
- synchronized로 임계영역(lock이 걸리는 영역)을 설정하는 방법 2가지
- 메서드 전체를 임계 영역으로 지정 = 1번에 1쓰레드로 최소화한다.
- 특정한 영역을 임계 영역으로 지정 = 객체의 참조변수 뒤에 괄호를 넣어 지정한다.
- 동기화에서는 private를 사용해야 의미가 있다.
- 출금 쓰레드를 동기화
- acc.withdraw = 출금 쓰레드를 호출해서 잔고를 불러온다.
- synchroinzed가 없으면 음수가 나오게 된다. (if문을 통과하므로)
- 그래서 A라는 쓰레드가 임계영역 안에 있으므로 자물쇠를 가지고 들어오게 되고, 다른 쓰레드가 들어오지 못하게 된다. 임계영역을 벗어나면 자물쇠를 반납한다.(= 임계영역 안에서는 하나의 쓰레드만 들어오게 된다.)
- synchroinzed가 붙으면 음수가 나오지 않는다.
.
- 동기화의 효율을 높이기 위해 wait(), notify()를 사용
- Object클래스에 정의되어 있으며, 동기화 블록 내에서만 사용할 수 있다.
- wait() - 객체의 lock을 풀고 쓰레드를 해당 객체의 waiting pool에 넣는다.
- notify() - waiting pool에서 대기중인 쓰레드 중의 하나를 깨운다.
- notifyAll() - waiting pool에서 대기중인 모든 쓰레드를 깨운다.
- 요리사는 Table에 음식을 추가. 손님은 Table의 음식을 소비
- 요리사와 손님이 같은 객체(Table)을 공유하므로 동기화가 필요
- Table - dish(음식)을 추가하는 메서드와 dish(음식)을 제거하는 메서드가 있다.
- Cook - 요리사는 table에 음식을 추가하는 일을 한다.
- Customer - 손님은 table의 음식을 먹는 일을 한다.
실행시,
예외1 : 요리사가 Table에 요리를 추가하는 과정에 손님이 요리를 먹음
예외2 : 하나 남은 요리를 손님2가 먹으려 하는데, 손님1이 먹음
문제점 : Table을 여러 쓰레드가 공유하기 때문에 작업 중에 끼어들기 발생
해결책 : Table의 add()와 remove()를 synchronized로 동기화
문제 : 예외는 발생하지 않지만, 손님(CUST2)이 Table에 lock건 상태를 지속
요리사가 Table의 lock을 얻을 수 없어서 음식을 추가하지 못함
문제점 : 음식이 없을 때, 손님이 Table의 lock을 쥐고 안놓는다.
요리사가 lock을 얻지 못해서 Table에 음식을 추가할 수 없다.
해결책 : 음식이 없을 때, wait()으로 손님이 lock을 풀고 기다리게 하자.
요리사가 음식을 추가하면, notify()로 손님에게 알리자.(손님이 lock을 재획득)
- 요리사는 테이블ㄹ이 가득 차면 대기(wait())하고, 음식을 추가하고 나면 손님에게 통보(notify())한다.
- 손님은 음식이 없으면 대기(wait())하고, 음식을 먹고나면 요리사에게 통보(notify())한다.
- 전과 달리 한 쓰레드가 lock을 오래 쥐는 일이 없어짐, 효율적이 됨!
- wait() / notify()의 대상이 불분명하다. -> Lock & Condition 사용