ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 💻 [OS 오퍼레이팅시스템] #12 | Synchronization (조건 동기) | CV, Monitor, 생산자 소비자 문제, Reader와 Writer 문제
    CS/OS 2022. 6. 13. 04:54

     

     


    💻 조건 동기 Condition Synchronization

     - 상호배제와 조건동기 
    1) Mutual Exclusion 상호배제 : 한 번에 하나의 쓰레드만 공유 자원에 접근 가능

    2) Condition Synchronization 조건 동기 : 다수 쓰레드의 접근 동기화, 다수 쓰레드의 실행을 순서화

    (특정 조건 만족할 때까지 대기, 조건 만족하면 재기시킴)


    💻 Condition Variables

    멀티쓰레드 프로그램에서, 스레드가 실행을 계속(재기)하기 전에 조건을 기다리는 경우가 많다.

    위 코드에서, while문에서 spinning하는 것이 비효율적이다. -> 해결해주자

     

     - Condition Variables (CV) 

    조건이 만족되기를 기다리는 공유변수

    - 어떤 이벤트가 일어나기 전까지 쓰레드를 블락하는 방식에 쓰인다. 

    - 조건에 따른 waiting queue(대기 장소)이다.

    - mutex와 관련이 좀 있다.

    - 스레드는 CV에서 대기할 수 있으며 다른 쓰레드가 상태를 알려주면 깨어날 수 있다.

     

    [ 동작 2가지 ]

    - 조건만족할 때 까지 대기 : wait() : 쓰레드를 넣어 대기시킨다.

    - 조건만족하고 재기 : signal() : 대기하는 쓰레드 중 하나만 깨워준다. broadcast()함수는 모든 대기 쓰레드를 깨운다.

     

    C와 JAVA에서의 구현

     - CV의 필수 요소 

    1) State Variable (ex. done변수)

    2) Lock for the State Variable (ex. done변수도 공유자원이므로 mutex 필요)

    3) Loop checking a condition using State Variable (ex. while문 필요)

    하나라도 없으면 broken case. 무조건 3요소 모두 만족해야한다.

     

    * mutex할 때 파라미터로 &m 전달하는 이유

    : lock을 잡고 대기, 못깨워주는 일이 발생한다. atomic한 연산을 하기 위해 이렇게 전달

    Q. Thread1이 먼저 실행되는 경우 과정

    쓰레드1에서 lock걸고 wait()으로 자러가면서 lock을 풀어준다.

    쓰레드2가 끼어들어서 실행된다. lock걸고 done=1해주고 쓰레드1 깨워주고 lock을 풀어준다. 

    다시 쓰레드1에서 while문을 벗어나서( done=1이 되어서 탈출 가능) 이어서 실행되고 종료된다.

    * 깨워주는 것은 ready상태로 만드는 것이지 run상태로 만드는게 아니다.

     

    Q. Thread2이 먼저 실행되는 경우 과정

    쓰레드2에서 lock을 걸고 done=1해주고 signal()을 호출하는데 현재 자고있는 쓰레드 없으므로 그냥 넘어가고 unlock하고 끝난다. 

    이후 쓰레드 1이 실행되어 lock걸고 done=1이므로 while문 바로 탈출해서 unlock하고 끝난다.

     

    -> 뭐가 먼저 실행되든 실행 순서 흐름 잘 보장된다.

     

    Q. 위의 3가지 필수 요소 중 2번째 요소인 lock이 없다면?

    쓰레드1이 실행되고 if문 안에 들어오고, lock기능 없으므로 인터리빙될 수 있는데 여기서 인터리빙 됐다고 가정하면

    쓰레드2이 실행되고 done=1해주고(signal is lost) signal()호출하는데 자고있는 쓰레드 없으므로 그냥 넘어가고 끝나서

    다시 쓰레드1로 넘어오면 if문 안에서 wait()호출되어서 자러가는데 깨워줄 수 있는 쓰레드 없으므로 계속 자는 상황 발생

    더보기
    NO LOCK -> thread1이 계속 자는 상황 발생

     

    Q. 위의 3가지 필수 요소 중 3번째 요소인 Loop이 없다면?

    쓰레드2가 먼저 실행되었다고 하면 lock걸고 signal()호출하는데 자고있는 쓰레드 없으므로 그냥 넘어가는 상황 발생(signal is lost)

    이후 unlock해주고 끝난다.

    쓰레드1이 실행되고 lock걸고 wait()호출해서 자게되는데 깨워줄 쓰레드 없으므로 계속 자는 상황 발생

    더보기
    NO LOOP -> thread1이 계속 자는 상황 발생

     


    💻 생산자(Producer)와 소비자(Consumer) 문제 

     - 생산자 소비자 문제 

    bounded buffer 문제라고도 함 (여기서 buffer도 critical resource이므로 mutex 필요)

    - 생산자 : buffer에 push하는 역할 -> buffer가 max면 추가 불가능

    - 소비자 : buffer에서 get하는 역할 -> buffer가 0이라면 소비 불가능

     

     - 생산자 소비자 문제 using CV 

     Infinite Buffer라고 가정(생산자 입장에서 제약없으니까 GOOD)

    근데 여기 if는 사실 문제 생길 수 있음 -> while

    Infinite Buffer

     - bounded buffer 

    2명의 소비자와 1명의 생산자, 버퍼 MAX는 1

    밑에 코드는 사실 Broken Case -> if가 문제 -> while

    Broken Case : 생산자와 소비자의 event가 달라서 다른 CV를 써야한다.

    소비자는 생산자만 깨워야하고, 생산자는 소비자만 깨워야한다. 

    sol) 2개의 condition variable을 사용한다. (하나는 empty condition, 다른 하나는 fill condition)

    more efficient synchronization!!

    busy-waiting은 없다. 깨워줄 때까지 큐에서 쉬면서 대기한다.

     

     - signal의 의미 

    Mesa semantics : 쓰레드가 깨어나면 state variable을 다시 체크 해야한다. (위 문제 상황 해결)  if문 대신 while문을 사용

    Hoare semantics : 깨어난 쓰레드가 바로 실행될 수 있게 스케쥴링을 잘 해야한다.

    대부분 Mesa semantics 방법을 사용한다.


    💻 CV로서의 세마포어

     - 조건동기에 세마포어 사용 

    P() block 가능 (cv<0)     V()는 never block (++, 깨워줌)

    조건 만족 대기 -> waiting         다른 쓰레드가 깨워줌 -> signaling

     

    세마포어 값 0으로 초기화

    semaphore as CV

     - 생산자 소비자 문제 : 세마포어 사용

    생산자소비자문제 semaphore로 바꾸는 과정. 아직 불완전한 코드이다.

     

    생산자 소비자문제 working solution
    [세마포어 사용 생산자 소비자 문제 코드]&nbsp; &nbsp; 왼: bounded buffer&nbsp; &nbsp;오: infinite buffer


    💻 Monitor

     - Monitor in JAVA 

    동기화 기법의 한 종류. 키워드 하나에 알아서 unlock/lock 제공

    프로그램 라이브러리로 구현됨. 상호배제와 조건 변수 제공한다.


    💻 Readers and Writers 문제

     - Readers-Writers Problem 

    concurrent한 프로세스들 사이에서 공유되는 데이터 세트가 존재

    Readers : read만 가능 (어떠한 update X) -> 여러 reader들 한번에 접근 허용 (상호배제X -> 성능 up)

    Writers : read와 write 둘 다 가능 -> 무조건 한번에 한 기록자만 공유 자원 접근 가능

     

     - shared Data (각각 guard 필요) 

    - DB

    - int readcount =0;    -> reader가 있는지 없는지 확인

     

     - synchronization variable 세마포어 변수 

    세마포어 wsem은 1로 초기화 (for DB)

    세마포어 x는 1로 초기화 (for readcount)