본문 바로가기
-----ETC-----/C++ 성능 최적화 및 고급 테크닉 시리즈

[C++ 성능 최적화 및 고급 테크닉] Day 15: 멀티스레딩의 기본 개념

by cogito21_cpp 2024. 8. 1.
반응형

멀티스레딩의 중요성

멀티스레딩은 여러 스레드를 사용하여 동시에 작업을 수행함으로써 프로그램의 성능을 향상시키는 기법입니다. 이를 통해 CPU 자원을 효율적으로 사용하고, 응답성을 높일 수 있습니다.

기본 용어

  • 스레드(Thread): 프로세스 내에서 독립적으로 실행되는 코드의 흐름입니다.
  • 멀티스레딩(Multithreading): 여러 스레드를 사용하여 동시에 여러 작업을 수행하는 기법입니다.
  • 병렬 처리(Parallel Processing): 여러 프로세서나 코어에서 동시에 작업을 수행하는 기법입니다.
  • 경합(Concurrency): 여러 작업이 동시에 실행되는 것처럼 보이는 상태입니다.

C++에서의 멀티스레딩

C++11부터 표준 라이브러리에서 멀티스레딩을 지원하는 기능이 도입되었습니다. std::thread 클래스를 사용하여 스레드를 생성하고 관리할 수 있습니다.

 

기본 예제

1. 스레드 생성

스레드를 생성하고 실행하는 기본 예제입니다.

#include <iostream>
#include <thread>

void threadFunction() {
    std::cout << "Hello from thread!" << std::endl;
}

int main() {
    std::thread t(threadFunction); // 스레드 생성
    t.join(); // 메인 스레드가 생성된 스레드가 종료될 때까지 대기
    return 0;
}

 

2. 인자 전달

스레드에 인자를 전달하는 예제입니다.

#include <iostream>
#include <thread>

void threadFunction(int x) {
    std::cout << "Thread function with argument: " << x << std::endl;
}

int main() {
    int value = 42;
    std::thread t(threadFunction, value); // 스레드 생성 시 인자 전달
    t.join(); // 메인 스레드가 생성된 스레드가 종료될 때까지 대기
    return 0;
}

 

3. 람다 함수 사용

람다 함수를 사용하여 스레드를 생성하는 예제입니다.

#include <iostream>
#include <thread>

int main() {
    std::thread t([]{
        std::cout << "Hello from lambda function thread!" << std::endl;
    });
    t.join(); // 메인 스레드가 생성된 스레드가 종료될 때까지 대기
    return 0;
}

 

스레드 동기화

멀티스레딩에서 여러 스레드가 공유 자원에 접근할 때 동기화가 필요합니다. 동기화 문제를 해결하지 않으면 경합 조건(race condition)이나 데드락(deadlock) 같은 문제가 발생할 수 있습니다.

 

뮤텍스(Mutex)

뮤텍스는 상호 배제를 구현하는 동기화 기법입니다. std::mutex 클래스를 사용하여 뮤텍스를 생성하고, lockunlock 함수를 사용하여 뮤텍스를 잠그고 해제할 수 있습니다.

 

예제 코드

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

std::mutex mtx;

void printMessage(const std::string& msg) {
    std::lock_guard<std::mutex> lock(mtx);
    std::cout << msg << std::endl;
}

int main() {
    std::thread t1(printMessage, "Hello from thread 1");
    std::thread t2(printMessage, "Hello from thread 2");

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

    return 0;
}

 

위 예제에서는 std::lock_guard를 사용하여 자동으로 뮤텍스를 잠그고 해제합니다.

 

실습 문제

문제 1: 멀티스레딩과 동기화 구현하기

다음 코드에서 멀티스레딩을 사용하여 두 개의 스레드가 동시에 카운트를 증가시키도록 구현하세요. 동시에 뮤텍스를 사용하여 경합 조건을 방지하세요.

 

main.cpp

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

int counter = 0;
std::mutex mtx;

void incrementCounter() {
    for (int i = 0; i < 100000; ++i) {
        counter++;
    }
}

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

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

    std::cout << "Final counter value: " << counter << std::endl;
    return 0;
}

 

해답:

main.cpp (동기화 추가)

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

int counter = 0;
std::mutex mtx;

void incrementCounter() {
    for (int i = 0; i < 100000; ++i) {
        std::lock_guard<std::mutex> lock(mtx);
        counter++;
    }
}

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

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

    std::cout << "Final counter value: " << counter << std::endl;
    return 0;
}

 

이제 열다섯 번째 날의 학습을 마쳤습니다. 멀티스레딩의 기본 개념과 스레드 동기화 기법을 이해하고, 실습 문제를 통해 이를 구현하는 방법을 학습했습니다.

질문이나 피드백이 있으면 언제든지 댓글로 남겨 주세요. 내일은 "std::thread와 동기화 기법"에 대해 학습하겠습니다.

반응형