std::shared_mutex
| ヘッダ <shared_mutex> で定義 |
||
| class shared_mutex; |
(C++17以降) | |
shared_mutexクラスは、複数のスレッドによって同時にアクセスされる共有データを保護するために使用できる同期プリミティブです。排他的アクセスを容易にする他のミューテックス型とは対照的に、shared_mutexには2つのアクセスレベルがあります。
- shared - 複数のスレッドが同じミューテックスの所有権を共有できます。
- exclusive - 1つのスレッドのみがミューテックスを所有できます。
あるスレッドがexclusiveロック(lock、try_lockを介して)を取得した場合、他のスレッドは(sharedロックを含め)ロックを取得できません。
あるスレッドがsharedロック(lock_shared、try_lock_sharedを介して)を取得した場合、他のスレッドはexclusiveロックを取得できませんが、sharedロックは取得できます。
exclusiveロックがどのスレッドにも取得されていない場合にのみ、sharedロックを複数のスレッドが取得できます。
1つのスレッド内では、同時に取得できるロックは1つだけです(sharedまたはexclusive)。
共有ミューテックスは、共有データが任意の数のスレッドによって同時に安全に読み取られることができ、かつ、他のスレッドが同時に読み取りまたは書き込みをしていない場合にのみ、あるスレッドが同じデータを書き込むことができる場合に特に有用です。
shared_mutexクラスは、SharedMutexおよびStandardLayoutTypeのすべての要件を満たします。
目次 |
[編集] メンバー型
| メンバ型 | 定義 |
native_handle_type (任意*) |
実装定義 |
[編集] メンバー関数
| ミューテックスを構築します (public メンバ関数) | |
| ミューテックスを破棄します (public メンバ関数) | |
| operator= [削除] |
コピー代入不可 (public メンバ関数) |
排他ロック | |
| ミューテックスをロックします。ミューテックスが利用できない場合はブロックします (public メンバ関数) | |
| ミューテックスをロックしようとします。ミューテックスが利用できない場合は戻ります (public メンバ関数) | |
| ミューテックスをアンロックします (public メンバ関数) | |
| | |
| 共有所有権のためにミューテックスをロックします。ミューテックスが利用できない場合はブロックします (public メンバ関数) | |
| 共有所有権のためにミューテックスをロックしようとします。ミューテックスが利用できない場合は戻ります (public メンバ関数) | |
| ミューテックスをアンロックします (共有所有権) (public メンバ関数) | |
ネイティブハンドル | |
| 基になる実装定義のネイティブハンドルオブジェクトを返します (public メンバー関数) | |
[編集] 例
以下の出力はシングルコアマシンで生成されました。thread1が開始すると、初めてループに入り、increment()を呼び出し、続けてget()を呼び出します。しかし、返された値をstd::coutに出力する前に、スケジューラはthread1をスリープさせ、thread2を起動します。thread2は明らかに3回のループイテレーションすべてを一度に実行するのに十分な時間があります。thread1に戻ると、まだ最初のループイテレーション中で、最終的にカウンタのローカルコピーの値である1をstd::coutに出力し、残りの2回のループイテレーションを実行します。マルチコアマシンでは、どちらのスレッドもスリープさせられず、出力は昇順になる可能性が高くなります。
#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) |
共有相互排他機能を提供し、タイムアウト付きのロックを実装する (クラス) |
| (C++14) |
ムーブ可能な共有ミューテックス所有権ラッパーを実装する (クラステンプレート) |
| (C++11) |
ムーブ可能なミューテックス所有権ラッパーを実装する (クラステンプレート) |