Computer Science

프로세스 vs 쓰레드: 멀티 쓰레드의 이해와 고려사항

본명은이점례 2023. 9. 8. 02:28
728x90


프로세스와 쓰레드는 모두 프로그램 실행의 핵심적인 요소입니다. 이들은 독립적인 실행 단위로 작업을 수행하며, 자원 관리와 성능에 중요한 영향을 미칩니다. 이 글에서는 프로세스와 쓰레드의 차이점, 그리고 멀티 쓰레드 환경에서 고려해야 할 사항에 대해 살펴보겠습니다.

프로세스 vs 스레드

프로세스는 운영 체제에서 실행되는 독립적인 프로그램의 인스턴스입니다. 각 프로세스는 자체 주소 공간, 메모리, 파일 디스크립터 등을 가지며, 다른 프로세스와 독립적으로 실행됩니다. 이러한 분리된 환경은 안전성과 격리를 제공하지만, 프로세스 간 통신에는 오버헤드가 큽니다.

반면, 쓰레드는 경량 실행 단위로, 같은 프로세스 내에서 실행됩니다. 쓰레드는 프로세스의 주소 공간을 공유하며, 스레드 간의 통신 및 자원 공유가 더 쉽습니다. 그러나 이러한 자원 공유는 쓰레드 간의 동기화와 관련된 문제를 야기할 수 있으며, 이로 인해 예상치 못한 문제가 발생할 수 있습니다.

멀티 쓰레드

멀티 쓰레딩은 하나의 프로세스 내에서 여러 개의 쓰레드가 동시에 실행되는 개념입니다. 각 쓰레드는 독립적으로 작업을 수행할 수 있으므로, 멀티 쓰레드를 통해 병렬 처리와 작업 분배가 가능해집니다.

문제점과 해결책

하지만 멀티 쓰레드 환경에서는 몇 가지 주요한 문제가 발생할 수 있습니다.

- 경쟁 조건 (Race Condition):** 여러 쓰레드가 하나의 공유 자원에 접근하고 값을 변경하려고 할 때, 예상치 못한 동작이 발생할 수 있습니다.

- 데드락 (Deadlock):** 두 개 이상의 쓰레드가 서로를 기다리며 무한 대기 상태에 빠지는 경우를 데드락이라고 합니다.

이러한 문제를 해결하기 위해 다음과 같은 기술을 사용할 수 있습니다.

1. Mutex (상호 배제): 오직 하나의 쓰레드만 공유 자원에 접근할 수 있도록 하는 동기화 메커니즘입니다. 하지만 여러 쓰레드가 동시에 접근해야 하는 경우에는 성능 저하가 발생할 수 있으며, 잘못 사용하면 데드락 문제가 발생할 수 있습니다.

 

#include <iostream>
#include <thread>
#include <mutex>

std::mutex mtx;

void someFunction() {
    mtx.lock();
    // 공유 자원에 대한 작업 수행
    mtx.unlock();
}

int main() {
    std::thread t1(someFunction);
    std::thread t2(someFunction);

    t1.join();
    t2.join();

    return 0;
}


2. Semaphore (세마포어): 여러 개의 쓰레드가 공유 자원에 접근할 수 있도록 하는 동기화 메커니즘입니다. 그러나 복잡하며 오용하면 오류와 기아 상태 문제가 발생할 수 있습니다.

멀티 쓰레딩은 성능 향상과 작업의 병렬화를 가능하게 해주지만, 적절한 동기화와 예외 처리를 통해 발생할 수 있는 문제에 대비하는 것이 중요합니다. 프로세스와 쓰레드를 사용할 때는 상황과 요구 사항을 고려하여 적절한 실행 단위를 선택하고, 동기화 메커니즘을 활용하여 안정적인 다중 스레드 애플리케이션을 구축해야 합니다.

 

#include <iostream>
#include <thread>
#include <mutex>
#include <semaphore.h>

// 세마포어 생성
sem_t semaphore;

// 공유 자원
int sharedResource = 0;

void threadFunction(int threadID) {
    // 세마포어를 이용하여 공유 자원에 접근하기 전에 대기
    sem_wait(&semaphore);

    // 공유 자원에 접근하여 작업 수행
    std::cout << "Thread " << threadID << " is accessing the shared resource." << std::endl;
    sharedResource++; // 공유 자원을 증가시킴

    // 세마포어를 이용하여 공유 자원에 대한 접근 종료
    sem_post(&semaphore);
}

int main() {
    // 세마포어 초기화 (세마포어 값은 여기서 1로 설정)
    sem_init(&semaphore, 0, 1);

    std::thread t1(threadFunction, 1);
    std::thread t2(threadFunction, 2);

    t1.join();
    t2.join();

    // 세마포어 삭제
    sem_destroy(&semaphore);

    // 공유 자원 출력
    std::cout << "Shared Resource: " << sharedResource << std::endl;

    return 0;
}
728x90