[Java] thread - 동기화, wait(), notify()

2500 단어 JavaJava

자바의 정석을 통해 공부한 내용을 요약하였습니다.

쓰레드의 동기화

한 쓰레드가 진행 중인 작업을 다른 쓰레드가 간섭하지 못하도록 막는 것

  • 멀티쓰레드 프로세스의 경우 같은 프로세스 내의 자원을 공유해서 작업하기 때문에 서로의 작업에 영향을 주게 된다.
  • 한 쓰레드가 특정 작업을 끝마치기 전까지 다른 쓰레드가 방해하지 않도록 하는 것이 필요하다.
  • 그래서 도입된 개념이 '임계 영역(critical section)''잠금(lock)'이다.


1. synchronized

// 1. 메서드 전체를 임계 영역으로 지정
public synchronized void calcSum() {
	//...
}

// 2. 특정한 영역을 임계 영역으로 지정
synchronized(객체의 참조변수) {
	//...
}
  • 메서드 전체를 임계 영역으로 지정하는 방법과 특정한 영역을 블럭{}으로 감싸 임계 영역으로 지정하는 방법이 있다.
  • 임계 영역은 최소한으로 지정하는 것이 좋다.
  • 가능하면 메서드 전체를 지정하는 것 보다 특정 영역을 임계 영역으로 지정하는 것이 효율적이다.


2. wait()과 notify()

void wait(), void wiat(long timeout) - 메서드 호출 시 실행 중이던 쓰레드는 해당 객체의 waiting pool에서 대기
notify() - 메서드 호출 시 waiting pool의 쓰레드 중 임의의 쓰레드를 깨움
notifyAll() - 메서드 호출 시 waiting pool의 모든 쓰레드를 깨움

  • 특정 쓰레드가 객체의 락을 가진 상태에서 오랜 시간을 보내지 않도록 하는 것 또한 중요하다.
  • 이런 경우를 위해서 wait()과 notify()가 고안되었다.
  • 매개변수가 있는 wait()은 지정된 시간동안만 기다린 후 자동적으로 notify()가 호출되는 효과를 가진다.

기아 현상과 경쟁 상태

  • waiting pool에서 통지를 받지 못하고 계속 대기하는 쓰레드가 있을 수 있다.
    이러한 현상을 기아현상(starvation)이라 한다.
  • 기아현상을 막기 위해서는 notify()보다 notifyAll()을 써주는 것이 좋다.
  • notifyAll()은 waiting pool에 있는 모든 쓰레드를 꺠워주는 것이어서 여러 쓰레드가 lock을 얻기 위해 서로 경쟁하게 된다.
    이러한 현상을 경쟁 상태(race condition)이라 한다.
  • 경쟁 상태를 개선하기 위해서는 쓰레드를 구별해서 통지하는 것이 필요하다.
    이럴 경우에는 Lock과 Condition을 이용해야 한다.

좋은 웹페이지 즐겨찾기