모니터 - 동시성 처리

텐저린티·2024년 1월 17일
0

알쓸신잡

목록 보기
10/10
post-thumbnail

모니터란?

개념

  • mutual exclusion 보장
  • 조건 따라 스레드 대기 상태 전환 기능 제공

언제 사용되나?

  • 한번에 하나의 스레드만 실행해야 할 때
  • 여러 스레드와 협업 필요할 때

구성요소 (M + CV)

Mutex

  • critical section 내 mutual exclusion 보장 위한 장치
  • critical section 진입 위해 mutext lock 필요
  • mutex lock 취득 못한 스레드는 entry queue에 들어간 후 waiting 상태로 전환
  • Mutex 락을 쥔 스레드가 락을 반환하면 락을 기다리며 큐에 대기상태로 있던 스레드 중 하나가 실행
  • Entry queue (critical section 진입 관련 큐)과 관련

Condition Variable

  • Waiting Queue 가짐
  • 조건이 충족되길 기다리는 스레드들이 대기 상태로 머무는 곳

Condition Variable 주요동작

동작설명
wait스레드가 자신을 CV 내 WaitingQ 에 넣음
signalWaitingQ 내 대기 스레드 하나 깨움
broadcastWaitingQ 내 대기 스레드 전부 깨움

두 개의 큐

종류설명
Entry QueueCritical Section 진입 대기 큐
Waiting Queue조건 충족 대기 큐

Bounded P/C problem

  • Producer 는 buffer 가 찼는지 계속 확인해야 함
  • Consumer 는 buffer 에 아이템이 있는 계속 확인해야 함
  • 모니터 활용해 해결 가능
  • CV 조건 확인 구문은 반드시 while 문 안에 배치
    - 락 획득 후 조건 확인 위해
while (q.isEmpty()) {
	wait(lock, emptyCV);
	// waiting queue 에서 나오면 여기가 PI임
}

Java 모니터

  • 모든 객체 내부적 모니터 존재
  • synchronized 키워드로 모니터 mutual exclusion 기능
  • 자바 모니터는 CV 하나만
    - 여러개가 필요한 경우 따로 설정하면 됨
  • 세 가지 동작
    - wait
    - notify
    - notifyAll (broadcast)
  • java.util.concurrent 에 동기화 클래스
class BoundedBuffer {

	private static final int SIZE = 5;
	
	private final int[] buffer = new int[SIZE];
	private int count = 0;

	// 메소드 레벨에 자바 모니터 뮤텍스 락 걸기
	// 자바 객체 내부에 있는 모니터를 사용한 것
	public synchronized void produce(int item) {
		while(count == 5) {
			wait();
		}
		buffer[count ++] = item;
		notifyAll();
	}

	public void consume() {
		int item = 0;
		// 코드 블럭에 자바 모니터 뮤텍스 락 걸기
		// 객체 인스턴스 (this)를 인자로 넘김
		synchronized (this) {
			while (count == 0) {
				wait();
			}
			item = buffer[-- count];
			notifyAll();
		}
		System.out.println("Consume: " + item);
	}
}

public class Main {
	public static void main(String[] args) throws {
		BoundedBuffer buffer = new BoundedBuffer();
		Thread consumer = new Thread(() -> buffer.consume());
		Thread producer = new Thread(() -> buffer.produce());

		consumer.start();
		producer.start();

		consumer.join();
		producer.join();
		// done
	}
}
profile
개발하고 말테야

0개의 댓글