sync & wait& notify & notifyAll

man soup·2020년 10월 23일
0

자바 문법

목록 보기
14/15

동기화(sync)

  • 쓰레드에 lock을 거는게 아니라 특정 모니터 객체에 lock을 거는 것
  • ex) sync void foo() {} 는 void food(){ sync(this)} 와 같은 코드

모니터

  • 하나의 데이터(객체)마다 하나의 모니터를 결합할 수 있다.
  • 모니터는 결합된 데이터(객체)가 동시에 두개 이상 의 스레드에 의해 접근 할 수 없도록 막는 잠금(lock)기능을 제공함으로써 동기화 수행
  • 데이터(객체)에 모니터를 결합하면 하나의 스레드가 그 데이터를 사용하는 동안에는 다른 스레드들이 그 데이터를 사용할 수 없게 된다.

wait()

  • 어떤객체.wait 메소드는 어떤 객체에 대한 락을 얻은 상황에서만 사용가능 아니면 error발생
    • 만약 sync 메소드 안에서 어떤객체a.wait()사용했다면 error
    • 왜냐하면 sycn 메소드는 this에 대한 lock을 얻은 거지 어떤객체a에 대해 얻은게 아니기 때문
  • ( wait()는 this.wait()임 )
  • wait 메소드 호출시 현재 쓰레드는 어떤객체에 대한 락을 반환하고 waiting 상태로 전환
  • blocked와 다른 상태로 lock을 기다리는게 아닌 notify를 기다림
  • 다른 쓰레드에 의해 notify받으면 깨어난 후 다시 락을 얻으려 시도
  • 락을 얻으면 interruptException을 던짐 ( 나 일어났다~ 알리는 것 )
  • 락을 얻지 못하면 blocked됨

guarded block

  • 어떤 조건을 만족할때 특정 행동을 할 수 있게 하는 것
  • ex) 버퍼가 비어있지 않는 경우에만 자원을 가져가게 하는 경우 ( producer/ consumer )
  • 방법1) while(isEmpty){} get() 하면 비어있는 동안 빈 while문을 돌면서 기다림
  • cpu 시간 낭비
  • 방법2) while(isEmpty) { this.wait(); } get();
  • wait을 사용해 lock을 반납 후 쓰레드는 waiting 상태로 바꾸고 cpu를 반납하면 cpu 시간 낭비 제거
  • wait 상태에서 깨어나려면 다른 쓰레드가 notify해줘야함
  • notify받으면 깨어난 후 자신의 lock( 어떤객체a.wait()이면 a의 락)

notify vs notifyAll

  • notify를 호출하면 waiting 상태의 쓰레드 중 하나를 무작위로 깨운다
  • nofityAll을 호출하면 waiting 상태의 모든 쓰레드를 깨운다.
  • 어차피 깨어난 쓰레드 중 하나만 작업을 수행할 수 있는데 왜 notifyAll이 필요할까?
  • producer/consumer 상황에서 여러 생산자와 소비자가 있고 자원을 담는 그릇의 크기는 1이라고 가정
    1. 쭉 잘 실행되다가 어느 순간 생산자가 put메소드 사용하고 자원을 넣고 nofity메소드 호출후 메소드 나감
    1. nofity에 의해 깨어난 쓰레드가 만약 생산자 쓰레드라면 이미 채워져있는 것을 확인 후 다시 wait상태로 돌아감
    1. 자원과 관련된 모든 쓰레드들 모두 waiting 상태
    1. 아무도 nofity해줄 수 없으므로 무한 대기 상태가 됨
  • 그러므로 notify가 아닌 notifyAll이 필요하다

출처 :
1. https://docs.oracle.com/javase/tutorial/essential/concurrency/guardmeth.html
2.
https://stackoverflow.com/questions/37026/java-notify-vs-notifyall-all-over-again
3.
https://stackoverflow.com/questions/7842265/difference-between-synchronized-block-with-wait-notify-and-without-them
4.
https://happy-coding-day.tistory.com/8#:~:text=Monitor(%EB%AA%A8%EB%8B%88%ED%84%B0)%EC%9D%98%20%EA%B0%9C%EB%85%90&text=%EC%9E%90%EB%B0%94%EC%97%90%EC%84%9C%EB%8A%94%20synchronized%20%EB%A9%94%EC%86%8C%EB%93%9C%EA%B0%80,%EC%9E%91%EC%97%85%EC%9D%84%20%EC%88%98%ED%96%89%ED%95%98%EA%B2%8C%20%EB%90%9C%EB%8B%A4.

profile
안녕하세요

0개의 댓글