스레딩 (Threading)
프로세스 간 통신 (Interprocess Communication)
IPC 방법들
- 프로세스 종료 상태: 프로세스가 종료될 때 반환하는 상태 코드.
- 파이프: 한 프로세스의 출력이 다른 프로세스의 입력으로 연결되는 통신 메커니즘.
- 신호: 프로세스 간에 비동기적으로 메시지를 전달하는 방법.
- 파일: 여러 프로세스가 읽고 쓸 수 있는 공통 파일을 사용하여 데이터를 공유.
- 소켓: 네트워크를 통해 데이터를 주고받는 통신 메커니즘.
- 공유 메모리: 여러 프로세스가 동일한 메모리 공간을 공유하여 통신.
- 메시지 큐: 프로세스 간에 메시지를 큐 형태로 주고받는 방법.
- 세마포어: 프로세스 간의 동기화를 위한 카운팅 메커니즘.
- 조건 변수: 특정 조건이 충족될 때까지 프로세스를 블록하는 동기화 메커니즘.
스레드 (Threads)
스레드의 개념
- 스레드는 프로세스와 개념적으로 유사한 추상화를 제공합니다.
- 스레드는 논리적 제어 흐름을 나타냅니다.
- 주요 차이점:
- 하나의 프로세스는 여러 스레드를 가질 수 있습니다.
- 하나의 프로세스 내의 두 스레드는 두 프로세스 또는 다른 프로세스 내의 스레드보다 덜 격리되어 있습니다.
- 특히, 하나의 프로세스 내의 스레드는 메모리 맵을 공유합니다.
스레드와 프로세스 비교
- 스레드는 메모리 맵과 권한 및 커널 리소스를 공유합니다.
- 스레드는 프로세스보다 훨씬 저렴합니다.
- 스레드 간 통신은 공유 메모리로 인해 간단합니다.
스레드의 장점
- 비용 절감: 스레드는 프로세스보다 메모리와 자원을 덜 사용합니다.
- 빠른 통신: 공유 메모리를 통해 스레드 간 상태 공유가 용이합니다.
스레드의 단점
- 동시 접근 문제: 공유 자원에 대한 동시 접근이 매우 까다롭습니다.
- 스레드 안전 문제: 많은 기존 API가 스레드 안전하지 않습니다.
스레드 사용 사례
스레드를 사용하는 적절한 작업
- 빠른 제어 변화: 병렬 작업 간의 빠른 제어 변화가 필요한 작업.
- 대규모 공유 데이터 구조: 많은 대규모 공유 데이터 구조를 사용하는 작업.
- 고속 계산: 단일 CPU에서 수행할 수 있는 것보다 더 빠른 계산이 필요한 작업.
스레드 간 통신
스레드 간 통신 메커니즘
- 스레드는 메모리를 공유하기 때문에 상태를 쉽게 공유할 수 있습니다.
- 파이프: 한 스레드의 출력이 다른 스레드의 입력으로 사용되는 통신 메커니즘.
- 메시지 큐: 스레드 간에 메시지를 큐 형태로 주고받는 방법.
- 신호: 스레드 간에 비동기적으로 메시지를 전달하는 방법.
- 세마포어: 스레드 간의 동기화를 위한 카운팅 메커니즘.
IPC 메커니즘과의 중복
- 스레드 간 통신 메커니즘은 IPC 메커니즘과 중복될 수 있습니다.
- 예:
kill() 대신 pthread_kill()을 사용하여 스레드 간 신호를 전달.
멀티스레딩 (Multi-threading)
멀티스레딩의 예시
- 정렬 알고리즘: 매우 긴 데이터를 정렬할 때 멀티스레딩을 사용하여 성능 향상.
- 동시성 예제: 여러 스레드를 사용하여 작업을 병렬로 처리하여 성능 최적화.
동기화 메커니즘 추가 설명
뮤텍스 (Mutexes)
- 뮤텍스 초기화:
pthread_mutex_init을 사용하여 뮤텍스를 초기화합니다.
- 뮤텍스 잠금/해제:
pthread_mutex_lock과 pthread_mutex_unlock을 사용하여 뮤텍스를 잠금 및 해제합니다.
- 재귀 뮤텍스: 재귀적으로 잠글 수 있는 뮤텍스. 재귀 속성을 통해 초기화할 수 있습니다.
조건 변수 (Condition Variables)
- 조건 변수 초기화:
pthread_cond_init을 사용하여 조건 변수를 초기화합니다.
- 조건 변수 대기:
pthread_cond_wait을 사용하여 조건 변수를 기다립니다.
- 조건 변수 신호:
pthread_cond_signal 또는 pthread_cond_broadcast를 사용하여 조건 변수를 신호합니다.
세마포어 (Semaphores)
- 세마포어 초기화:
sem_init을 사용하여 세마포어를 초기화합니다.
- 세마포어 대기/포스트:
sem_wait과 sem_post를 사용하여 세마포어를 대기 및 신호합니다.
- 세마포어 시도 대기:
sem_trywait을 사용하여 세마포어를 즉시 대기 시도합니다. 성공하면 0을 반환하고 실패하면 EAGAIN을 반환합니다.
멀티스레딩의 예시 코드
#include <pthread.h>
#include <semaphore.h>
#include <stdio.h>
#include <stdbool.h>
pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
bool done = false;
void *thread_function(void *arg) {
pthread_mutex_lock(&lock);
while (!done) {
pthread_cond_wait(&cond, &lock);
}
pthread_mutex_unlock(&lock);
printf("Thread completed\n");
return NULL;
}
void signal_done() {
pthread_mutex_lock(&lock);
done = true;
pthread_mutex_unlock(&lock);
pthread_cond_signal(&cond);
}
int main() {
pthread_t t;
pthread_create(&t, NULL, thread_function, NULL);
usleep(100000);
signal_done();
pthread_join(t, NULL);
return 0;
}
- 이 프로그램은 조건 변수와 뮤텍스를 사용하여
done 플래그가 설정될 때까지 스레드를 블록합니다.
종합
- 스레드는 프로세스보다 메모리와 자원을 덜 사용하며, 빠른 통신이 가능합니다.
- 스레드 간 통신은 공유 메모리를 통해 간단하지만, 동기화가 필요합니다.
- 동기화 메커니즘으로는 뮤텍스, 조건 변수, 세마포어 등이 있습니다.
- 스레드는 병렬 작업과 고속 계산에 적합합니다.
- 스레드를 적절히 사용하면 멀티코어 CPU의 성능을 극대화할 수 있습니다.