Day 64

ChangWoo·2023년 6월 8일
0

자바의 정석

목록 보기
63/71
post-thumbnail

ch 13-30~33 쓰레드의 동기화

쓰레드의 동기화(synchronization)

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

synchronized를 이용한 동기화

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

    1. 메서드 전체를 임계 영역으로 지정 = 1번에 1쓰레드로 최소화한다.
    1. 특정한 영역을 임계 영역으로 지정 = 객체의 참조변수 뒤에 괄호를 넣어 지정한다.

synchronized를 이용한 동기화 - 예제

  • 동기화에서는 private를 사용해야 의미가 있다.
  • 출금 쓰레드를 동기화
  • acc.withdraw = 출금 쓰레드를 호출해서 잔고를 불러온다.
  • synchroinzed가 없으면 음수가 나오게 된다. (if문을 통과하므로)
  • 그래서 A라는 쓰레드가 임계영역 안에 있으므로 자물쇠를 가지고 들어오게 되고, 다른 쓰레드가 들어오지 못하게 된다. 임계영역을 벗어나면 자물쇠를 반납한다.(= 임계영역 안에서는 하나의 쓰레드만 들어오게 된다.)
  • synchroinzed가 붙으면 음수가 나오지 않는다# ch 13-30~33 쓰레드의 동기화

쓰레드의 동기화(synchronization)

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

synchronized를 이용한 동기화

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

    1. 메서드 전체를 임계 영역으로 지정 = 1번에 1쓰레드로 최소화한다.
    1. 특정한 영역을 임계 영역으로 지정 = 객체의 참조변수 뒤에 괄호를 넣어 지정한다.

synchronized를 이용한 동기화 - 예제

  • 동기화에서는 private를 사용해야 의미가 있다.
  • 출금 쓰레드를 동기화
  • acc.withdraw = 출금 쓰레드를 호출해서 잔고를 불러온다.
  • synchroinzed가 없으면 음수가 나오게 된다. (if문을 통과하므로)
  • 그래서 A라는 쓰레드가 임계영역 안에 있으므로 자물쇠를 가지고 들어오게 되고, 다른 쓰레드가 들어오지 못하게 된다. 임계영역을 벗어나면 자물쇠를 반납한다.(= 임계영역 안에서는 하나의 쓰레드만 들어오게 된다.)
  • synchroinzed가 붙으면 음수가 나오지 않는다.
    .

ch 13-34~36 wait()과 notify

wait()과 notify()

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

wait()과 notify() - 예제1

  • 요리사는 Table에 음식을 추가. 손님은 Table의 음식을 소비
  • 요리사와 손님이 같은 객체(Table)을 공유하므로 동기화가 필요
  • Table - dish(음식)을 추가하는 메서드와 dish(음식)을 제거하는 메서드가 있다.
  • Cook - 요리사는 table에 음식을 추가하는 일을 한다.
  • Customer - 손님은 table의 음식을 먹는 일을 한다.

    실행시,

wait()과 notify() - 예제1 실행결과(동기화X)

예외1 : 요리사가 Table에 요리를 추가하는 과정에 손님이 요리를 먹음
예외2 : 하나 남은 요리를 손님2가 먹으려 하는데, 손님1이 먹음

wait()과 notify() - 예제1 문제점과 해결책

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

wait()과 notify() - 예제1 실행결과(동기화O)

문제 : 예외는 발생하지 않지만, 손님(CUST2)이 Table에 lock건 상태를 지속
요리사가 Table의 lock을 얻을 수 없어서 음식을 추가하지 못함

wait()과 notify() - 예제2

문제점 : 음식이 없을 때, 손님이 Table의 lock을 쥐고 안놓는다.
요리사가 lock을 얻지 못해서 Table에 음식을 추가할 수 없다.
해결책 : 음식이 없을 때, wait()으로 손님이 lock을 풀고 기다리게 하자.
요리사가 음식을 추가하면, notify()로 손님에게 알리자.(손님이 lock을 재획득)

  • 요리사는 테이블ㄹ이 가득 차면 대기(wait())하고, 음식을 추가하고 나면 손님에게 통보(notify())한다.
  • 손님은 음식이 없으면 대기(wait())하고, 음식을 먹고나면 요리사에게 통보(notify())한다.

wait()과 notify() - 예제2 실행결과

  • 전과 달리 한 쓰레드가 lock을 오래 쥐는 일이 없어짐, 효율적이 됨!
  • wait() / notify()의 대상이 불분명하다. -> Lock & Condition 사용
profile
한 걸음 한 걸음 나아가는 개발자

0개의 댓글