struct semaphore {
int count;
queueType queue;
};
void semWait (semaphore s)
{
s.count--;
if (s.count < 0) {
/* 요청한 프로세스를 s.queue에 연결 */
/* 요청한 프로세스를 블록 상태로 전이시킴 */
}
}
void semSignal (semaphore s)
{
s.count++;
if (s.count <= 0) {
/* s.queue에 연결되어 있는 프로세스를 큐에서 제거 */
/* 프로세스의 상태를 실행 가능으로 전이시키고 ready list에 연결 */
}
}
semWait
연산semWait
을 호출한 프로세스는 블록됨semSignal
연산semWait
연산에 의해 블록된 프로세스들을 깨움struct binary_semaphore {
/* 0 아니면 1만의 값을 가짐 */
enum {zero, one} value;
queueType queue;
};
void semWaitB(binary_semaphore s)
{
if (s.value == one)
/* s.value가 1이면 0으로 바꾸고 나옴 => 다음에 수행 */
s.value = zero;
else{
/* s.value가 0일 때 수행 */
/* 요청한 프로세스를 s.queue에 연결 */
/* 요청한 프로세스를 블록 상태로 전이시킴 */
}
}
void semSignalB(semaphore s)
{
if(s.queue is empty())
s.value = one;
else {
/* s.queue에서 프로세스 P를 제거 */
/* 프로세스 P의 상태를 실행 가능으로 전이시키고 ready list에 연결 */
}
}
semWaitB
연산semWaitB
를 호출한 프로세스는 블록semSignalB
연산생산자(프로세스) : D
소비자(프로세스) : A, B, C
~ 중간 생략 ~
12. A,B까지 블록 큐에 들어가게 되면 s=-4이 됨 13. D가 들어오고 semSignal 호출 14. C가 준비 큐에 들어가게 되고 s는 -2가 됨const int b = /* 프로세스 개수 */
semaphore s = 1;
void P(int i)
{
while (true) {
semWait(s);
/* 임계영역 */
semSignal(s);
/* 임계영역 이후 코드 */
}
}
void main()
{
parbegin (P(1), P(2), ... , P(n))
}
parbegin
을 통해 n개의 프로세스 실행semaphore s
의 값은 1로 초기화하고 코드 실행semSignal
호출생산자 :
while(true){
/* 데이터 V를 생산 */
b[in] = V;
in++;
}
소비자 :
while(true){
while(in <= out)
/* 대기 */
w = b[out]
out = ++;
/* 데이터 w를 소비 */
}
/* 생산자 소비자 프로그램 */
int n; /* 전역 변수 n => 전역변수의 비교를 통해 조정 */
binary_semaphore s = 1, delay = 0;
/* 생산자의 경우 => 무한루프를 돌면서 데이터 생성 */
void producer()
{
while (true) {
produce(); /* 데이터 생성 */
/* 버퍼의 임계 영역 설정 => s에 대해 LOCK을 만듦 */
semWaitB(s); /* 소비자의 버퍼 사용 방지 위해 버퍼 LOCK*/
append(); /* 버퍼 append */
n++;
if (n==1) semSignalB(delay); /* 소비자에게 버퍼가 채워졌음을 알림 */
semSignalB(s); /* 버퍼 UNLOCK */
}
}
/* 소비자 프로세스의 경우 => */
void consumer()
{
semWaitB(delay); /* 생산자가 생성한 것을 기다림 */
while (true) {
semWaitB(s); /* 생산자의 버퍼 사용 방지 위해 버퍼 LOCK */
take(); /* 버퍼에서 데이터 꺼내기 */
n--;
semSignalB(s); /* 버퍼 UNLOCK */
consume();
if (n==0) semWaitB(delay); /* 생산자에게 버퍼가 비워졌음을 알림 => 기다리는 상태 */
}
}
void main()
{
n = 0;
parbegin (producer, consumer); /* 생산자와 소비자 두 프로세서 모두 실행*/
}
int n;
binary_semaphore s = 1, delay = 0;
void producer()
{
while (true) {
produce();
semWaitB(s);
append();
n++;
if (n==1) semSignalB(delay);
semSignalB(s);
}
}
void consumer()
{
int m; /* 지역변수 선언 */
semWaitB(delay);
while (true) {
semWaitB(s); /* 생산자의 버퍼 사용 방지 위해 버퍼 LOCK */
take(); /* 버퍼에서 데이터 꺼내기 */
n--;
m = n; /* 소비자의 임계영역 내에 보조변수 m 사용 */
semSignalB(s); /* 버퍼 UNLOCK */
consume();
if (m==0) semWaitB(delay); /* 생산자에게 버퍼가 비워졌음을 알림 => 기다리는 상태 */
}
}
void main()
{
n = 0;
parbegin (producer, consumer); /* 생산자와 소비자 두 프로세서 모두 실행*/
}
semaphore n = 0, s = 1,
void producer()
{
while (true) {
produce(); /* 데이터 생성 */
semWaitB(s); /* s에 대해 락 걸기 */
append(); /* 큐에 넣기 */
semSignal(s)
semSignal(n); /* 데이터가 있다는 사실을 알림 */
}
}
void consumer()
{
while (true) {
semWait(n); /* semWaitB(s)와 순서가 바뀌면 교착상태가 발생할 가능성이 있음 */
semWaitB(s); /* 데이터를 꺼내기 위한 버퍼 LOCK */
take(); /* 버퍼에서 데이터 꺼내기 */
semSignalB(s); /* 버퍼 UNLOCK */
consume();
}
}
void main()
{
parbegin (producer, consumer); /* 생산자와 소비자 두 프로세서 모두 실행*/
}
producer:
while (true) {
/* 데이터 V를 생산 */
while ((in + 1) % n == out)
/* 대기 */
b[in] = V;
in = (in + 1) % n;
}
consumer:
while (true) {
while(in == out)
/* 대기 */
w = b[out];
out = (out+1) % n
/* 데이터 w를 생산 */
}
- 일반적인 원형 큐 자료구조와 같이 끝까지 들어가게 되면 다시 처음으로 돌아감
- 큐의 개수가 정해져 있음
- **큐의 공간보다 넘치게 생산할 수 없음**
- 큐의 **공간을 확인하는 세마포어** 필요
/* 유한 버퍼를 사용하는 생산자 소비자 프로그램 */
const int sizeofbuffer = /* 버퍼 사이즈 */
semaphore s = 1, n = 0, e = sizeofbuffer; /* 큐에 넣을 수 있는 공간 확인용 */
void producer()
{
while (true){
produce();
semWait(e); /* e: 버퍼에서 빈 공간의 수 */
semWait(s); /* 버퍼에 대해서 LOCK */
append();
semSignal(s);
semSignal(n);
}
}
void consumer()
{
while (true) {
semWait(n);
semWait(s);
take();
semSignal(s);
semSignal(e); /* 버퍼가 비기를 기다리는 생산자 깨워주는 코드 */
consume();
}
}
void main()
{
parbegin(producer, consumer)
}
semWait(s)
{
/* 밑에 있는 코드들이 상호 배제를 확인하는 코드 */
while (compare_and_swap(s.flag, 0, 1) == 1)
/* 대기 */
/* 임계 영역의 진입 */
a.count--;
if (a.count < 0) {
/* 요청한 프로세스를 a.queue에 연결 */
/* 요청한 프로세스를 블록 상태로 전이시키고 s.flag를 0으로 설정 */
}
/* 임계 영역 나옴 */
s.flag = 0;
}
semSignal(s)
{
while (compare_and_swap(s.flag, 0, 1) == 1)
/* 대기 */
/* 임계 영역 진입 */
s.count++;
if (s.count <= 0) {
/* s.queue에 블록된 프로세스를 큐에서 제거 */
/* 전이시키고 준비 큐에 연결 */
}
/* 임계 영역 나옴 */
s.flag = 0;
}
semWait(s)
{
인터럽트 금지;
s.count--;
if (s.count < 0) {
/* 요청한 프로세스를 s.queue에 연결 */
/* 요청한 프로세스를 블록 상태로 전이시킴(또한 인터럽트 허용) */
}
else
인터럽트 허용;
}
semSignal(s)
{
인터럽트 금지;
s.count++;
if (s.count <= 0) {
/* s.queue에 블록된 프로세스를 큐에서 제거 */
/* 전이시키고 준비 큐에 연결 */
}
인터럽트 허용;
}