2020-11-14 운영체제 기초 - 동기화문제
동기화의 문제
- Bounded-Buffer-Problem
- Readers and Writers Problem
- Dining-Philosophers Problem
Bounded-Buffer-Problem
-
버퍼는 Circular Buffer의 형태
-
Producer-Consumer 문제가 있다.
-
이 구조에서 Producer 프로세스와 Consumer 프로세스가 있다. Producer는 공유버퍼에 데이터를 만들어서 넣는다.
-
Producer의 역할
- Empty 버퍼가 있나 체크. 없으면 기다린다.
- 공유데이터에 lock을 건다.
- Empty Buffer에 데이터 입력 및 Buffer 조작
- Lock을 푼다.
- Full Buffer 하나 증가
-
Consumer의 역할
- full 버퍼가 있는지 체크. 없으면 기다린다.
- 공유데이터에 lock을 건다.
- Full Buffer에서 데이터를 꺼내고 Buffer를 조작.
- Lock을 푼다.
- Empty Buffer 하나 증가
-
Shared data : Buffer 자체 및 Buffer 조작 변수(empty/full buffer의 시작 위치)
-
세마포어변수 : semaphore full =0, empty = n, mutex = 1(lock을 걸기 위해)
-
// Producer do { ... P(empty); V(mutex); .. add x to buffer ... V(mutex); V(full); } while(1); // Consumer do { P(full); P(mutex); ... remove an item from buffer to y ... V(mutex); V(empty); ... consume the item in y } while (1);
-
Readers-Wirters Problem
- 한 프로세스가 DB에 쓰기 중일때는 다른 프로세스가 접근하면 안된다.
- 읽기는 동시에 여럿이 해도 된다.
- 해결법
- Writer가 데이터베이스에 접근 허가를 아직 얻지 못한 상태에서는 대기중인 모든 Reader들은 다 데이터베이스에 접근하게 해준다.
- Writer는 대기중인 Reader가 하나도 없을 때 데이터베이스 접근이 허용된다.
- 일단 Writer가 데이터베이스에 접근 중이면 Reader들은 접근이 금지된다.
- Writer가 데이터베이스에서 빠져나가야만 Reader의 접근이 허용.
- Shared Data
- 데이터베이스 자체
- readcount => 현재 데이터베이스에 접근 중인 Reader의 수.
- 동기화 변수
- mutex : 공유변수 readcount를 접근하는 코드(critical section)의 mutex exclusion 보장을 위해 사용
- db : Reader, Writer가 공유 데이터베이스 자체를 올바르게 접근하게 하는 역할
// shared data
int readcount = 0;
// synchronization variables
semaphore mutex = 1, db = 1;
// Writer
P(db);
...
writing DB is performed
...
V(db);
// Reader
P(mutex);
readcount++;
if (readcount == 1) P(db); // block writer
V(mutex);
...
reading db is performed
...
P(mutex);
readcount--;
if (readcount == 0) V(db); // enable writer
V(mutex); => starvation 발생가능.
- writer가 오래 기다리면 starvation이 발생할 수 있다.
Dining-Philosophers Problem
-
출처 : https://miro.medium.com/max/383/1*YABO-JVRfRKZNd-hAnJnjQ.png
-
동기화 변수 : semaphore chopstick[5]; => 모든 값은 1로 시작한다.
// Philosopher i
do {
P(chopstick[i]);
P(chopstick[(i+1) % 5]);
...
eat();
...
V(chopstick[i]);
V(chopstick[(i+1) % 5]);
...
think();
...
} while(1);
- 위 코드는 데드락의 문제점이 존재, 모든 철학자가 동시에 배가 고파서 왼쪽 젓가락을 집어버린 경우
- 해결 방안
- 4명의 철학자만 테이블에 동시에 앉을 수 있게한다.
- 젓가락을 2개 모두 집을 수 있을때만 젓가락을 집을 수 있게한다.
- 비대칭
- 짝수(홀수) 철학자는 왼쪽(오른쪽) 젓가락부터 집는다.
Monitor
-
세마포어의 문제점
- 코딩하기 힘들다
- 정확성의 입증이 어렵다
- 자발적 협력이 필요
- 한번의 실수가 모든 시스템에 치명적인 영향
-
동시 수행중인 프로세스 사이에서 abstract data type의 안전한 공유를 보장하기 위한 high-level synchronization contsruct
-
monitor monitor-name { // shared variable declartion procedure body P1(....) { ... } procedure body P2(....) { ... } procedure body P3(....) { ... } { initialization code } }
-
-
모니터 내에서는 한번에 하나의 프로세스만이 활동 가능
-
프로그래머가 동기화 제약 조건을 명시적으로 코딩할 필요가 없다.
-
프로세스가 모니터안에서 기다릴 수 있도록 하기 위해 condition variable 사용 => condition x, y;
-
condition variable은 wait, signal 연산에 의해서만 접근 가능. => x.wait()
-
x.wait()를 invoke한 프로세스는 다른 프로세스가 x.signal()을 invoke 하기전까지 suspend된다.
-
x.signal();은 정확하게 하나의 suspend된 프로세스를 resume한다. suspend된 프로세스가 없으면 아무일도 일어나지 않는다.
-
Bounded-Buffer problem 모니터 코드
-
{ int buffer[N]; condition full, empty; // condition var은 값을 가지지 않고 자신의 큐에 프로세스를 매달아서 sleep 시키거나 큐에서 프로세스를 깨우는 역할만 한다. void produce(int x) { if there is no empty buffer empty.wait(); add x to an empty buffer full.signal(); } void consume(int *x) { if there is no full buffer full.wait(); remove an item from buffer and store it to *x empty.signal(); } }
-