std:: shared_mutex
|
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Member functions | ||||
| Exclusive locking | ||||
| Shared locking | ||||
| Native handle | ||||
|
헤더 파일에 정의됨
<shared_mutex>
|
||
|
class
shared_mutex
;
|
(C++17부터) | |
shared_mutex
클래스는 공유 데이터가 여러 스레드에 의해 동시에 접근되는 것을 보호하기 위해 사용할 수 있는 동기화 기본 요소입니다. 배타적 접근을 용이하게 하는 다른 뮤텍스 유형과 달리, shared_mutex는 두 가지 수준의 접근을 가집니다:
- shared - 여러 스레드가 동일한 뮤텍스의 소유권을 공유할 수 있습니다.
- exclusive - 뮤텍스를 소유할 수 있는 스레드는 오직 하나뿐입니다.
한 스레드가 exclusive lock을 획득한 경우( lock , try_lock 통해), 다른 스레드들은 lock을 획득할 수 없습니다( shared lock 포함).
한 스레드가 shared lock을 획득한 경우( lock_shared , try_lock_shared 를 통해), 다른 스레드는 exclusive lock을 획득할 수 없지만, shared lock은 획득할 수 있습니다.
오직 exclusive 잠금이 어떤 스레드에서도 획득되지 않은 경우에만, shared 잠금을 여러 스레드가 획득할 수 있습니다.
하나의 스레드 내에서는 동시에 하나의 락( shared 또는 exclusive )만 획득할 수 있습니다.
공유 뮤텍스는 공유 데이터가 여러 스레드에 의해 동시에 안전하게 읽힐 수 있지만, 다른 스레드가 동시에 읽거나 쓰고 있지 않을 때만 스레드가 동일한 데이터를 쓸 수 있는 경우에 특히 유용합니다.
shared_mutex
클래스는
SharedMutex
와
StandardLayoutType
의 모든 요구사항을 충족합니다.
목차 |
멤버 타입
| 멤버 타입 | 정의 |
native_handle_type
(
선택적*
)
|
구현 정의 |
멤버 함수
|
뮤텍스를 생성함
(public member function) |
|
|
뮤텍스를 파괴함
(public member function) |
|
|
operator=
[deleted]
|
복사 할당 불가
(public member function) |
배타적 잠금 |
|
|
뮤텍스를 잠금, 사용 불가능할 경우 차단됨
(public member function) |
|
|
뮤텍스 잠금을 시도함, 사용 불가능할 경우 반환됨
(public member function) |
|
|
뮤텍스 잠금을 해제함
(public member function) |
|
공유 잠금 |
|
|
공유 소유권을 위해 뮤텍스를 잠금, 사용 불가능할 경우 차단됨
(public member function) |
|
|
공유 소유권을 위해 뮤텍스 잠금을 시도함, 사용 불가능할 경우 반환됨
(public member function) |
|
|
뮤텍스 잠금을 해제함 (공유 소유권)
(public member function) |
|
네이티브 핸들 |
|
|
기본 구현 정의 네이티브 핸들 객체를 반환함
(public member function) |
|
예제
아래 출력은 단일 코어 머신에서 생성되었습니다.
thread1
이 시작되면 첫 번째 루프 진입 시
increment()
를 호출한 후
get()
를 호출합니다. 그러나 반환된 값을
std::
cout
에 출력하기 전에 스케줄러가
thread1
을 슬립 상태로 전환하고
thread2
를 깨웁니다. 이로 인해
thread2
는 세 번의 루프 반복을 모두 한 번에 실행할 충분한 시간을 갖게 됩니다.
thread1
으로 돌아와서, 여전히 첫 번째 루프 반복 중인 상태에서 마침내 카운터 값의 로컬 복사본인
1
을
std::cout
에 출력한 후 나머지 두 번의 루프 반복을 실행합니다. 멀티코어 머신에서는 스레드가 슬립 상태로 전환되지 않으며, 출력이 오름차순으로 나타날 가능성이 더 높습니다.
#include <iostream> #include <mutex> #include <shared_mutex> #include <syncstream> #include <thread> class ThreadSafeCounter { public: ThreadSafeCounter() = default; // Multiple threads/readers can read the counter's value at the same time. unsigned int get() const { std::shared_lock lock(mutex_); return value_; } // Only one thread/writer can increment/write the counter's value. void increment() { std::unique_lock lock(mutex_); ++value_; } // Only one thread/writer can reset/write the counter's value. void reset() { std::unique_lock lock(mutex_); value_ = 0; } private: mutable std::shared_mutex mutex_; unsigned int value_{}; }; int main() { ThreadSafeCounter counter; auto increment_and_print = [&counter]() { for (int i{}; i != 3; ++i) { counter.increment(); std::osyncstream(std::cout) << std::this_thread::get_id() << ' ' << counter.get() << '\n'; } }; std::thread thread1(increment_and_print); std::thread thread2(increment_and_print); thread1.join(); thread2.join(); }
가능한 출력:
123084176803584 2 123084176803584 3 123084176803584 4 123084185655040 1 123084185655040 5 123084185655040 6
참고 항목
|
(C++14)
|
공유 상호 배제 기능을 제공하고 타임아웃으로 잠금을 구현함
(class) |
|
(C++14)
|
이동 가능한 공유 뮤텍스 소유권 래퍼를 구현함
(class template) |
|
(C++11)
|
이동 가능한 뮤텍스 소유권 래퍼를 구현함
(class template) |