-
동기화(Synchronization) 2CS/OS(운영체제) 2022. 6. 12. 15:41728x90
Mutual Exclusion(상호 배제)는 지정된 시점에 단일 스레드만 공유 자원에 접근할수 있어야 함을 의미한다.
그러나 꼭 mutex만이 동시 구축에 필요한 요소는 아니다.
조건 동기화 - 다중 스레드 접근 동기화
시스템 상태가 특정 조건을 충족할 때 까지 대기하여 여러 스레드의 실행 순서를 지정하는 것.
상태 변수(Condition Variables)
상태 변수 CV - CV는 이벤트가 발생할 때 까지 스레드가 차단하는 방법이다.
- CV는 조건에 대한 대기 큐이다.(디익스트라 알고리즘의 아이디어)
- CV는 mutex와 연관되며, 개념적으로 몇 조건과 관련이 있다.
Operation - 스레드는 상태 변수에서 대기할 수 있으며, 다른 스레드가 조건을 알릴 때 wake up 된다.
대기 조건 : wait(). 조건이 충족되지 않을 경우 스레드가 대기열에 자신을 배치할 수 있다.
조건 신호 : signal(). 한 스레드가 대기 중인 스레드를 wake up 시킨다. broadcast() 명령어는 대기중인 모든 스레드를 wake up 시킨다.
상태 변수 API
구현
- mutexes와 함께 사용하도록 설계 되어 있다.
- Pthread는 일반적으로 C프로그램에서 사용된다.(모니터가 없기 때문)
- java에서 모니터의 컨텍스트 내에서 상태 변수를 사용할 수 있다.
Join()
간단한 Join() 예시는 상태 변수를 적절히 사용하기 위한 기본 요구 사항을 보여준다.
- 상태 변수
- 상태 변수에 대한 Lock
- 상태 변수를 이용한 Loop 점검
[Thread 1] int main(int argc, char* argv[]){ pthread_t c; pthread_create(&c, NULL, child, NULL); thr_join(); return 0; } void thr_join(){ pthread_mutex_lock(&m); while(done==0) pthread_cond_wait(&c, &m); pthread_mutex_unlock(m); } [Thread 2] void* child(void* arg){ thr_exit(); return NULL; } void* thr_exit(){ pthread_mutex_lock(&m); done = 1; pthread_cond_signal(&c); pthread_mutex_unlock(&m); }
1. 첫번째 시나리오
Thread 1이 join()을 실행하면, Thread 2가 exit()를 실행한다.
Thread 1 - lock()을 얻고, wait()을 호출한다. (sleep하고 lock을 atomically하게 해제한다.
Thread 2 - lock()을 얻고, 상태 변수(done)을 1로 설정한다, signal()을 호출한다. -> Thread 1이 활성화되어 lock을 해제 한 후 루프 중에 종료한다.
2. 두번째 시나리오
Thread 2가 exit()를 실행하면, Thread 1이 join()을 실행한다.
Thread 2 - lock()을 얻고, 상태 변수(done)을 1로 설정한다, signal()을 호출한다. ( signal()은 잠들어있는 thread가 없기 때문에 아무런 효과도 발휘하지 않는다.)
Thread 1 - lock()을 얻고, 상태 변수를 1로 설정한다. done이 이미 1로 설정되었으므로 반복문으로 들어가지 않는다.
생산자/소비자 문제(Producer/Consumer problem)
- 다익스트라에 의해 처음 제기된 bounded buffer problem 이라고도 한다.
- 일반화된 Semaphore를 이해하기 위해서 쓰인다.
해결법
- consumer는 오직 producer가 깨울 수 있고, producer는 오직 consumer가 깨울 수 있게 한다.
- 상태 변수를 2개 사용한다. (empty,fill)
- 더 효율적인 동기화를 가능하게 한다.
신호의 의미에 대한 해석
1. Mesa Semantics
- wake up된 스레드는 wake up 후 상태 변수를 다시 확인해야 한다.
2. Hoare Semantics
- wake up된 스레드가 즉시 실행된다는 보다 강력한 보장이 있음.
대부분의 시스템은 Mesa Semantics를 사용한다. (항상 while문을 사용하기 때문.)
상태 변수로서의 semaphore
- 세마포어는 스레드의 조건이 참이 될 때 까지 진행을 멈추기를 원할 때 유용하다.
- 세마포어 값을 변경하는 데 사용할 수 있는 작업은 P()와 V()뿐이다. (초기 설정 제외)
- P()는 차단할 수 있지만, V()는 차단하지 않는다.
- 세마포어는 상호 배제 , 조건 동기화 모두에 사용된다.
Example.
sem_t s; void * child (void *args) { printf(“child\n”); sem_post(&s); return NULL; } int main(int argc, char *argv[]) { sem_init(&s, 0, 0); printf(“parent: begin\n”); pthread_t c; pthread_create(c, NULL, child, NULL); sem_wait(&s); printf(“parent: end\n”); return 0; }
세마포어의 단점
구조화되지 않은 구조
- 프로그램에서 wait과 signal 작업이 산란할 수 있음.
- 그 결과 디버깅이 어려워짐.
- 정확성과 성능 문제를 모두 유발함.
- Example - Deadlock : 두 개 이상의 프로세스가 각각 다른 프로세스 중 하나를 위해 대기하고 있기 때문에 진행할 수 없는 상황
Monitor in Java
프로세스 동기화를 위한 편리하고 효과적인 메커니즘을 제공하는 고급 추상화
- 구조화된 구조의 장점을 유지하면서, 둘 이상의 스레드로 절차 또는 변수에 안전하게 엑세스 할 수 있도록 하기 위한 thread safe 클래스,객체 또는 모듈
- 프로그램 라이브러리로도 구현됨.
- 프로세스가 procedure중 하나를 호출하여 모니터에 들어간다.
- 모니터는 자원에 접근하기 위한 상호 배제 기능을 제공한다.
- 모니터에서는 프로세스들이 서로 signal할 수 있는 상태 변수가 포함되어 있다.
Readers-Writers Problem
Data set이 여러 프로세스 간에 공유됨.
Readers - 데이터 셋만 읽고 업데이트는 수행하지 않음.
Writers - 읽고 쓸 수 있음
이 결과 한 명의 Writer만 동시에 공유 데이터에 접근 할 수 있고, 여러 Readers는 동시에 읽을 수 있도록 허용함.
공유 데이터 - DB , int readcount = 0;
상태 변수 - DB의 경우, semaphore wsem이 1로 초기화 , readcount를 위해 semaphore x가 1로 초기화됨.
728x90'CS > OS(운영체제)' 카테고리의 다른 글
메모리 관리(Memory Management) (0) 2022.06.12 교착 상태(DeadLock) (0) 2022.06.12 동기화(Synchronization) (0) 2022.06.01 스레드(Thread) (0) 2022.05.30 인터럽트(Interrupts) (0) 2022.04.17