5/30 세마포어(Semaphore)

JK·2023년 5월 30일

세마포어(Semaphore)

세마포어는 동시성 프로그래밍에서 공유된 자원에 대한 접근을 제어하거나 여러 스레드 또는 프로세스의 실행을 조정하는 동기화 기법입니다.

  1. 정의:
    세마포어는 음이 아닌 값을 가질 수 있는 정수 변수로, 두 가지 기본 연산인 세마포어 다운 (P)과 세마포어 업 (V)를 지원합니다.

  2. 연산:

  • 세마포어 다운 (P): 세마포어 값이 0보다 큰 경우 값을 1 감소시키고 계속 실행합니다. 그렇지 않으면 값이 0인 경우 호출한 스레드/프로세스가 블록되어 대기 상태가 됩니다. 대기 상태에서는 세마포어가 0이 아닐 때까지 기다립니다.

  • 세마포어 업 (V): 세마포어 값을 1 증가시킵니다. 세마포어에 대기 중인 스레드/프로세스가 있는 경우 그 중 하나를 깨웁니다.

  1. 세마포어의 종류:
  • 이진 세마포어: 이진 세마포어는 세마포어 값이 0 또는 1인 특수한 경우입니다. 주로 상호 배제를 위해 사용되며, 한 번에 하나의 스레드/프로세스만 공유 자원에 접근할 수 있도록 합니다.

  • 카운팅 세마포어: 카운팅 세마포어는 음이 아닌 값을 가질 수 있습니다. 주로 여러 스레드/프로세스가 공유 자원에 동시에 접근할 수 있는 개수를 제어하는 데 사용됩니다.

  1. 주요 사용 시나리오:
  • 상호 배제: 이진 세마포어를 사용하여 코드의 임계 영역을 보호하여 한 번에 하나의 스레드/프로세스만 임계 영역을 실행하도록 보장할 수 있습니다.

  • 자원 동기화: 세마포어를 사용하여 여러 스레드/프로세스의 실행을 조정하고, 특정 조건이나 이벤트가 발생하기 전까지 대기하도록 보장할 수 있습니다.

  • 생산자-소비자 문제: 세마포어를 사용하여 생산자와 소비자 스레드 간의 상호작용을 동기화하여 데이터의 생산과 소비를 조절할 수 있습니다.

  1. 세마포어의 구현:
  • 운영체제에서 세마포어를 구현하는 다양한 방법이 있습니다.
    위 내용을 토대로 세마포어의 개념과 사용 방법을 이해하고, 병행 프로그래밍에서 동기화를 위해 세마포어를 적절히 활용할 수 있습니다.

세마포어(Semaphore)의 예시 코드

세마포어에 대해 공부하면서 예시 코드를 찾아봤습니다
세마포어의 세마 다운(semaphore down)과 세마 업(semaphore up)은 동기화를 위해 사용되는 기본적인 연산입니다. 세마 다운은 세마포어의 값을 감소시키고, 만약 값이 0이면 대기하도록 합니다. 세마 업은 세마포어의 값을 증가시키고, 대기 중인 스레드가 있다면 깨웁니다.

아래는 세마포어의 세마 다운과 세마 업을 구현한 예시 코드입니다.

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>

#define NUM_THREADS 5

sem_t semaphore;

void* thread_function(void* arg) {
    int thread_id = *(int*)arg;
    
    printf("Thread %d: Waiting for semaphore down...\n", thread_id);
    sem_wait(&semaphore); // 세마 다운
    
    printf("Thread %d: Entered critical section.\n", thread_id);
    // 여기에서 임계 영역에 접근하는 작업을 수행합니다.
    
    printf("Thread %d: Exiting critical section.\n", thread_id);
    
    sem_post(&semaphore); // 세마 업
    printf("Thread %d: Semaphore up.\n", thread_id);
    
    pthread_exit(NULL);
}

int main() {
    pthread_t threads[NUM_THREADS];
    int thread_ids[NUM_THREADS];
    int i;
    
    sem_init(&semaphore, 0, 1); // 세마포어 초기화
    
    // 스레드 생성
    for (i = 0; i < NUM_THREADS; i++) {
        thread_ids[i] = i;
        pthread_create(&threads[i], NULL, thread_function, (void*)&thread_ids[i]);
    }
    
    // 스레드 종료 대기
    for (i = 0; i < NUM_THREADS; i++) {
        pthread_join(threads[i], NULL);
    }
    
    sem_destroy(&semaphore); // 세마포어 제거
    
    return 0;
}

세마포어에 대해 공부하면서 어려웠던 점은 초기에 개념을 이해하는 것이었습니다. 세마포어는 동기화와 상호 배제를 위해 사용되는 개념이라는 것을 이해하는 데 시간이 걸렸고, 세마포어의 작동 방식과 다양한 상황에서의 활용 방법을 익히는 것도 도전이었습니다.

하지만 공부를 진행하면서 세마포어의 중요성과 유용성을 깨달았습니다. 세마포어는 병렬 프로그래밍에서 스레드 간의 동기화와 상호 배제를 가능하게 해주는 강력한 도구입니다. 여러 스레드가 공유 자원에 안전하게 접근하고 조작할 수 있도록 도와줍니다.

또한, 세마포어를 사용하여 교착 상태(deadlock)와 기아(starvation)를 예방하는 것이 중요하다는 것을 깨달았습니다. 세마포어를 올바르게 활용하면 프로그램의 안정성과 성능을 향상시킬 수 있습니다.

세마포어에 대한 공부는 동시에 다른 동기화 메커니즘들과도 관련이 있어서, 전반적인 병렬 프로그래밍 지식을 향상시킬 수 있는 기회였습니다. 어려움을 겪으며 노력하고 이해하는 과정을 통해 세마포어와 동기화에 대한 지식을 확장할 수 있었습니다

profile
^^

0개의 댓글