모니터 (wait, signal, broadcast)

Bonjugi·2024년 12월 29일
0

참고자료

두번째 영상은 정말 좋아요 구독을 누를수밖에 없는 엄청난 퀄리티이다.
비슷한 내용은 대부분 영상의 정보를 활용했다. 시간이 없다면 영상만 봐도 좋을듯 하다.

사전에 알아두면 좋을만한 링크

모니터?

모니터는 언제 필요한가?

  • 한번에 하나의 쓰레드만 실행 되어야 할때
  • 여러 쓰레드와 협업이 필요 할때

즉 동시성에 대한 얘기.

모니터의 구성요소

  • mutext : 크리티컬섹션에서 mutual exclusion 을 보장하는 장치.
    • mutext lock을 취득하지 못한 쓰레드는 큐에 들어서 waiting 상태로 대기.
    • mutext lock을 쥔 스레가 lock 을 반환하면, 락 기다리던 대기 쓰레드중 하나가 실행된다
  • cv (condition variable)
    • wq (wating queue) 를 갖고있음. 조건이 충족되길 기다리는 쓰레드들이 대기상태로 머무르는 큐

자바는 synchronized 키워드와 함께 모니터와 락을 사용한다.

cv (condition variable) 의 주요동작

  • wait - 자기 자신을 cv 의 wq 에 넣고 대기상태로 전환함
  • signal - wq 에서 대기중인 쓰레드중 하나를 깨움
  • broadcast - 전부 깨움

모니터와 크리티컬섹션

전반적으로 모니터와 함께 크리티컬섹션을 처리하는 모습.

출처 : https://www.youtube.com/watch?v=Dms1oBmRAlo

사용되는 2개의 큐

  • entry q : 크리티컬섹션 진입을 기다리는 큐
  • waiting q : 조건이 충족되길 기다리는 큐
    • cv에 의해 관리되는 큐

JAVA 모니터 특징

  • 모든 객체는 모니터를 갖고있다.
  • 모니터의 3가지 동작 (모두 자신이 속한 객체가 속한 모니터의 cv에 대한 동작들임)
    • wait - wait
    • notify - signal
    • notifyAll - broadcast
  • 모니터에는 mutex lock 이 있다.
  • mutual exclusion 은 synchronized 키워드로 해결한다.
  • cv (condition variable) 는 하나만 내부에 가지고 있다.

notify는 객체의 모니터에 대기중인 쓰레드들중 랜덤으로 1개를 깨운다. (어떤게 될지는 비결정적)
notifyAll은 객체의 모니터에 대기중인 쓰레드들을 모두 깨운다.

대체로 notifyAll이 더 실용적일 거라고 함. (여기저기 대부분 예제가 notifyAll 이긴 하더라)

But in most cases, it would be more viable to implement notifyAll().
출처-밸덩

생산소비 문제 해결

출처 : https://www.youtube.com/watch?v=Dms1oBmRAlo

특이사항 :

  1. while 쓰는 이유는, OS에 따라 다르지만 wait 였던걸 잘못 깨워버리는 경우도 있다고 한다. 따라서 깨어난 후, 다시 한번 조건을 체크하기 위해 if가 아니라 while을 쓴것.
  2. 자바 객체의 모니터는 condition variable 이 1개만 있다고 간주한다. 따라서 선별적으로 signal 해줄수가 없다. 특정 쓰레드를 깨우는 notify 보다는, 모니터 내 대기큐에 있는 모든 쓰레드를 깨우는 notifyAll 를 썼다. 해서, 방금 notifyAll() 하며 일을 마치고 나온 쓰레드도 다시 entry q에 들어갔다가 또다시 자원을 할당받고 수행할수도 있는 비효율성이 있어보인다.

자바에서 조건에 맞는 쓰레드만 깨우려면 java.util.concurrent 의 ReantratLock + Condition 를 활용하면 된다.

결론

동시성을 활용하기 위해 모니터라는 개념을 알았다.
모니터는 java에만 있는 개념은 아니며 몇가지 기능 (wait, signal, broadcast) 을 이용해 여러 쓰레드간에 협력을 만들어낼수 있다.
java는 wait, notify, notifyAll로 대응된다. notify 대신 notifyAll 이 편리 할 것이다.
java는 객체가 모니터를 가지고 있으며, 모니터 내에 condition variable은 1개만 관리하고 있다.

쓰레드는 os에 따라 비결정적 이라는 특징 때문에 while을 쓰는 모습 등 저수준 코드로는 구현이 어렵다.
가독성, 편의성, 기능 모든면에서 1.5의 동시성라이브러리 java.util.concurrent 를 이용하는게 좋다.
그럼에도 저수준 코드도 이해 해 두는것은 동시성라이브러리를 깊게 이해 하는데 도움이 된다.

0개의 댓글