shared timed mutex
개요
std::shared_timed_mutex
는 여러 스레드가 데이터를 읽는 것을 허용하면서, 데이터 쓰기는 단 하나의 스레드만 허용하는 읽기-쓰기 잠금(Read-Write Lock)을 구현합니다. 읽기 작업이 쓰기 작업보다 훨씬 빈번하게 발생하는 경우, 일반 std::mutex
보다 높은 성능을 제공할 수 있습니다.
C++ 버전별 주요 키워드 도입 시기
- C++14:
std::shared_timed_mutex
가 표준에 추가되었습니다. - C++14:
std::shared_lock
이std::shared_timed_mutex
와 함께 사용하기 위한 RAII 래퍼로 추가되었습니다.
내용 설명
std::shared_timed_mutex
는 두 가지 종류의 잠금을 제공합니다.
- 공유 잠금 (Shared Lock): 여러 스레드가 동시에 획득할 수 있는 잠금입니다. 주로 데이터 읽기 작업에 사용됩니다.
std::shared_lock
을 통해 RAII 방식으로 안전하게 관리할 수 있습니다. - 배타적 잠금 (Exclusive Lock): 단 하나의 스레드만 획득할 수 있는 잠금입니다. 주로 데이터 쓰기 작업에 사용됩니다.
std::unique_lock
또는std::lock_guard
로 관리합니다.
쓰기 스레드가 배타적 잠금을 요청하면, 기존의 모든 읽기 스레드가 공유 잠금을 해제할 때까지 대기합니다. 반대로, 읽기 스레드가 공유 잠금을 사용 중일 때는 다른 읽기 스레드들은 바로 진입할 수 있지만, 쓰기 스레드는 대기해야 합니다.
예제 코드
#include <iostream>
#include <thread>
#include <mutex>
#include <shared_mutex>
#include <vector>
#include <chrono>
class ThreadSafeCounter {
public:
ThreadSafeCounter() = default;
// 여러 스레드가 동시에 호출 가능 (읽기)
unsigned int get() const {
std::shared_lock<std::shared_timed_mutex> lock(mutex_);
return value_;
}
// 한 번에 한 스레드만 호출 가능 (쓰기)
void increment() {
std::unique_lock<std::shared_timed_mutex> lock(mutex_);
value_++;
}
private:
mutable std::shared_timed_mutex mutex_;
unsigned int value_ = 0;
};
int main() {
ThreadSafeCounter counter;
auto writer = [&]() {
for (int i = 0; i < 5; ++i) {
counter.increment();
std::cout << "Writer: incremented to " << counter.get() << std::endl;
std::this_thread::sleep_for(std::chrono::milliseconds(500));
}
};
auto reader = [&](int id) {
for (int i = 0; i < 5; ++i) {
std::cout << "Reader " << id << ": sees value " << counter.get() << std::endl;
std::this_thread::sleep_for(std::chrono::milliseconds(200));
}
};
std::thread writer_thread(writer);
std::vector<std::thread> reader_threads;
for (int i = 0; i < 3; ++i) {
reader_threads.emplace_back(reader, i + 1);
}
writer_thread.join();
for (auto& t : reader_threads) {
t.join();
}
return 0;
}
실행 결과
Reader 1: sees value 0
Reader 2: sees value 0
Reader 3: sees value 0
Writer: incremented to 1
Reader 1: sees value 1
Reader 2: sees value 1
Reader 3: sees value 1
Reader 1: sees value 1
Reader 2: sees value 1
Writer: incremented to 2
Reader 3: sees value 2
...
(실행 시점에 따라 순서는 달라질 수 있습니다.)
활용팁
- 읽기 위주 환경에 최적: 공유 데이터에 대한 읽기 작업이 쓰기 작업보다 압도적으로 많을 때 사용하면 동시성을 높여 성능 이점을 얻을 수 있습니다.
std::shared_lock
활용: 읽기 잠금을 위해서는 RAII 패턴을 따르는std::shared_lock
을 사용하는 것이 안전하고 편리합니다.- 쓰기 기아(Writer Starvation) 주의: 읽기 스레드가 계속해서 잠금을 획득하는 경우, 쓰기 스레드가 잠금을 얻지 못하고 무한정 대기하는 '쓰기 기아' 상태가 발생할 수 있습니다. 시스템 설계 시 이를 고려해야 합니다.
'개발 > C++ (98,03,11,14,17,20,23)' 카테고리의 다른 글
Modern C++ : std::mutex (11, 14, 17) (1) | 2025.10.18 |
---|---|
Modern C++ : std::thread (11) (0) | 2025.10.17 |
Modern C++ : std::exception (98, 11, 17) (0) | 2025.10.16 |
Modern C++ : std::weak_ptr (11) (1) | 2025.10.15 |
Modern C++ : std::shared_ptr (11, 17) (0) | 2025.10.14 |
Modern C++ : std::unique_ptr (11, 14) (0) | 2025.10.13 |
Modern C++ : std::format (20) (0) | 2025.10.12 |
Modern C++ : std::ranges (20) (0) | 2025.10.11 |