티스토리 뷰

728x90

모니터

  • mutual exclusion(상호배제)를 보장
  • 조건에 따라 스레드가 wait 상태로 전환 가능

모니터는 언제 사용할까?

  • 한번에 하나의 스레드만 실행돼야 할 때
  • 여러 스레드와 협업(cooperation)이 필요할 때

구성요소

  • mutex (Mutual Exclusion Object)
    • Critical section(임계영역)에서 mutual exclusion을 보장하는 장치
    • Critical section에 진입하려면 mutex lock을 취득해야 함
    • mutex lock을 취득하지 못한 스레드는 큐에 들어간 후 wait 상태로 전환
    • mutex lock을 쥔 스레드가 lock을 반환하면 대기 중인 스레드 하나가 실행
  • Condition variable
    • Wait queue(조건이 충족되길 기다리는 스레드들이 대기상태로 머무르는 곳)를 가짐
    • 1개 이상일 수도 있음. 구현하기 나름
    • 조건은 누가 언제 정하지?
      • 모니터를 구현하기 나름
      • 자바의 경우 java.util.concurrent.locks.Condition 인터페이스로 정의할 수 있음
    • condition variable에서 주요 operation
      • Wait : 스레드가 자기 자신을 waiting queue에 넣고 대기 상태로 전환
      • Ex) 자기가 기대한 조건이 층족되지 않았을 때 대기
      • Signal : waiting queue에서 대기 중인 스레드 중 하나를 깨움
      • broadcast : waiting queue에서 대기 중인 스레드 전부를 깨움

모니터에서 사용하는 2가지 큐

  • Entry queue
    • 뮤택스에서 관리
    • critical section에 진입을 기다리는 큐
    • poll의 우선순위는 구현에 따라 달라진다
      • 자바를 포함하여 일반적으로 FIFO
  • Waiting queue
    • condition variable에서 관리
    • 조건이 충족되길 기다리는 큐
    • waiting queue에 들어가는 스레드는 lock을 반환. (락을 쥔 상태로 대기상태에 들어가버리면 다른 스레드가 critical section에 진입할 수 없으므로)

Signal의 작동 방식

  • Signal and continue
    • 스레드가 Wq의 다른 스레드를 깨운 후 자신의 할 일을 마저 수행하는 것
    • 스레드 T1이 Wq의 다른 스레드 T2를 깨운 후 T1은 작업을 마저 수행한다. T2는 wait 하면서 뮤택스락을 반환했기 때문에 entry queue에 들어가서 락 획득을 기다린다.
    • wq에서 signal 받고 깨어난 직후 뮤택스락을 기다리기 위해 entry queue에 들어가서 기다리다가 뮤택스락을 획득했을 때 다시 wait조건(=conditional variable)에 걸려 waiting queue에서 또 대기해야할 수도 있음.
    • waiting queue 또는 entry queue에서 나올 경우 마지막 위치에서부터 이어 작업을 수행하고 condition variable에 의해 wait상태였다 깨어난 경우 다시 condition variable에 걸리는지 체크해야 하기 때문에 wait는 condition variable 조건을 가진 while문 안에서 실행해야 한다.
  • Signal and wait
    • 스레드 T1이 waiting queue의 다른 스레드 T2를 깨운 후 T1은 wait. T2가 이어서 할 일을 마치고 mutex lock을 release 하면 T1이 다시 깨어나서 이후 과정을 진행하는 것
  • 작동 방식은 사용하는 프로그래밍 언어와 런타임 시스템에서 결정함.
    • 자바의 경우 signal and continue 사용
    • signal and wait 방식을 쓰는 케이스는 많지 않다고 함. ex) POSIX Thread (C C++ 라이브러리)
class BoundedBuffer {
    
    private final int[] buffer = new int[5];
    private int count = 0;
    
    public synchronized void produce(int item) {
      while (count == 5) { wait(); } // wait를  while문 안에서 실행하는 예시
      buffer[count++] = item;
      notifyAll();
    }
}

 

java의 모니터

  • 자바에서 모든 객체는 내부적으로 모니터를 가진다
  • synchronized 키워드로 Mutual exclusion을 구현위 코드에서 this의 의미 : 자바의 모든 객체는 모니터가 있고 그 모니터엔 뮤택스락이 있으므로 자기 자신의 뮤택스 락을 쥐고 mutual exclusion에 들어가는 것이다
// 블록 사용. 파라미터로 lock을 넣어줘야 함
/*
this의 의미 : 자바의 모든 객체는 모니터가 있고 
그 모니터엔 뮤택스락이 있으므로 
자기 자신의 뮤택스 락을 쥐고 mutual exclusion에 들어가는 것이다
*/
synchronized (this) {
    count++;
}


// 메소드 전체를 임계영역으로 설정
// getCount() 메소드가 있는 객체의 뮤택스락을 쥐고 mutual exclusion으로 들어감
public synchronized int getCount() {
    return count;
}

 

 

  • 자바의 모니터는 condition variable을 1개만 가진다
    • 2개 이상의 condition variable을 사용하고 싶은 경우 따로 구현 필요

 

 

  • 동작
    • wait
    • signal : notify
    • broadcast : notifyAll

 

 

 

 

참고 : https://youtu.be/Dms1oBmRAlo?si=qFDKQ8Ytd5PE200c

728x90

'기초지식' 카테고리의 다른 글

Dockerfile, Docker Compose 간단 정리  (0) 2024.01.07
CQRS 패턴 간단 정리  (0) 2022.10.29
대규모 데이터를 다루기 위한 기초지식 - OS 캐시  (0) 2022.08.17
CPU bound, IO bound  (0) 2022.08.15
웹소켓 (Web Socket) 정리  (0) 2022.05.22
댓글
300x250
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/09   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30
글 보관함