본문 바로가기
프로그래밍 언어/C++

멀티 쓰레딩 - std::lock_guard

by 규봉봉이 2025. 5. 12.

멀티 쓰레딩에서 std::lock_guard는 왜 사용하는 걸까? 예시를 들어 설명하겠다.

 

멀티 쓰레드에서 lock을 잡을 때 아래와 같이 worker() 함수 안에서 lock을 잡는다.

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

int counter = 0;
std::mutex counter_mutex;

void worker() {
    counter_mutex.lock();
    if (counter == 1) { counter += 10; }
    else if (counter >= 10) { counter += 15; }
    else if (counter >= 50) { return; }
    else { ++counter; }

    std::cout << std::this_thread::get_id() << ": " << counter << '\n';

    counter_mutex.unlock();
}

int main() {
    std::cout << __func__ << ": " << counter << '\n';

    std::thread t1(worker);
    std::thread t2(worker);

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

    std::cout << __func__ << ": " << counter << '\n';
}

 

 

그런데 만일 lock()와 unlock() 사이에 다른 함수를 사용하고 이 함수가 예외를 호출한다면 unlock()이 제대로 호출이 안 될수도 있다. 그렇기 때문에 아래와 같이 std::lock_guard를 사용한다. std::lock_guard는 RAII(Resource Acquisition Is Initialization) 구조를 사용하기 때문에 객체 소멸 시점에 강제로 unlock()이 호출된다. 그러므로 위의 worker() 함수 종료 시점에 자연스럽게 unlock()이 호출된다.

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

int counter = 0;
std::mutex counter_mutex;

void worker() {
    std::lock_guard<std::mutex> lock(counter_mutex);
    if (counter == 1) { counter += 10; }
    else if (counter >= 10) { counter += 15; }
    else if (counter >= 50) { return; }
    else { ++counter; }

    std::cout << std::this_thread::get_id() << ": " << counter << '\n';
}

int main() {
    std::cout << __func__ << ": " << counter << '\n';

    std::thread t1(worker);
    std::thread t2(worker);

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

    std::cout << __func__ << ": " << counter << '\n';
}

 

위와 같이 수정이 가능하다.

'프로그래밍 언어 > C++' 카테고리의 다른 글

멀티쓰레딩 - Condition Variable  (0) 2025.05.13
멀티 쓰레딩 - try_lock  (0) 2025.05.13
싱글턴 패턴 적용  (0) 2024.08.21
std::count_if  (1) 2024.07.23
사용자 정의 리터럴(literal)  (1) 2024.07.23