개요
세마포는 일반화된 뮤텍스라고 생각할 수 있다.
세마포어 S는 정수값을 가지는 변수이며, 다음과 같이 P와 V라는 원자적 명령에 의해서만 접근할 수 있다. (P와 V는 각각 try와 increment를 뜻하는 네덜란드어 Proberen과 Verhogen의 머릿글자를 딴 것이다.)
P는 임계 구역에 들어가기 전에 수행되고, V는 임계 구역에서 나올 때 수행된다. 이때 변수 값을 수정하는 연산은 모두 원자성을 만족해야 한다. 다시 말해, 한 프로세스(또는 스레드)에서 세마포어 값을 변경하는 동안 다른 프로세스가 동시에 이 값을 변경해서는 안 된다.
P연산은 S를 1감소시키고, S가 0과 같으면 Wait를 한다. V는 S를 1증가시키며, 만약 세마포S가 0에서 1로 바뀌면 기다리고 있는 P를 깨우게 된다.
세마포어는 두가지 중요한 방법으로 사용될 수 있다. Mutal Exclusion과 Signaling의 두가지 방법론이 있다. Mutual Exclusion은 Lock과 동이라하게 세마포를 1로 초기화 시켜서 사용하는 방법이며, Signaling은 초기화를 0으로 해준다음 다른 스레드가 up시키는 방법으로 사용한다.
semaphore.h
int sem_init(sem_t * semaphore_p, int shared, unsigned initial_val);
만일 pshared매개 변수가 '0'이 아닌 값을 가지고 있다면, 그 세마포어는 프로세스들 간에 공유할 수 있다. 만일 매개 변수 pshared이 '0' 이라면, 프로세스내의 스레드들간에 세마포어를 공유할 수 있다. 성공할 경우 sem_init() 함수는 ‘0’ 값을 반환한다. 그렇지 않을 경우 ‘-1’ 값을 반환하고 errno값을 설정하여 오류를 표시한다.
int sem_destroy(sem_t* semaphore_p);
세마포에 할당한 메모리 공간을 해제한다.
int sem_post(sem_t* semaphore_p);
세마포 값을 1 증가시킨다. V
int sem_wait(sem_t* semaphore_p);
세마포 값을 1 감소시킨다. P
예제
#include <stdio.h>
#include <pthread.h>
#include <semaphore.h>
#include <unistd.h>
sem_t mutex;
void* thread(void* arg)
{
//wait
sem_wait(&mutex);
printf("\nEntered..\n");
//critical section
sleep(4);
//signal
printf("\nJust Exiting...\n");
sem_post(&mutex);
}
int main()
{
sem_init(&mutex, 0, 1);
pthread_t t1,t2;
pthread_create(&t1,NULL,thread,NULL);
sleep(2);
pthread_create(&t2,NULL,thread,NULL);
pthread_join(t1,NULL);
pthread_join(t2,NULL);
sem_destroy(&mutex);
return 0;
}