Namespaces
Variants

std:: shared_mutex

From cppreference.net
Concurrency support library
Threads
(C++11)
(C++20)
this_thread namespace
(C++11)
(C++11)
Cooperative cancellation
Mutual exclusion
(C++11)
shared_mutex
(C++17)
Generic lock management
Condition variables
(C++11)
Semaphores
Latches and Barriers
(C++20)
(C++20)
Futures
(C++11)
(C++11)
(C++11)
Safe reclamation
Hazard pointers
Atomic types
(C++11)
(C++20)
Initialization of atomic types
(C++11) (deprecated in C++20)
(C++11) (deprecated in C++20)
Memory ordering
(C++11) (deprecated in C++26)
Free functions for atomic operations
Free functions for atomic flags
ヘッダーで定義 <shared_mutex>
class shared_mutex ;
(C++17以降)

shared_mutex クラスは、共有データが複数のスレッドから同時にアクセスされるのを防ぐために使用できる同期プリミティブです。排他的アクセスを提供する他のミューテックスタイプとは対照的に、shared_mutexには2つのアクセスレベルがあります:

  • shared - 同じミューテックスの所有権を複数のスレッドが共有できます。
  • exclusive - ミューテックスを所有できるスレッドは一つだけです。

あるスレッドが exclusive ロックを取得した場合( lock try_lock を通じて)、他のスレッドはロックを取得できません( shared ロックを含む)。

あるスレッドが shared ロック( lock_shared try_lock_shared を通じて)を取得している場合、他のスレッドは exclusive ロックを取得することはできませんが、 shared ロックを取得することは可能です。

排他的 ロックがどのスレッドにも取得されていない場合にのみ、 共有 ロックは複数のスレッドによって取得できます。

1つのスレッド内では、同時に取得できるロック( shared または exclusive )は1つだけです。

共有ミューテックスは、共有データが任意の数のスレッドによって同時に安全に読み取り可能であるが、他のスレッドが読み取りまたは書き込みを行っていない場合にのみ、スレッドが同じデータを書き込める場合に特に有用です。

shared_mutex クラスは、 SharedMutex および StandardLayoutType のすべての要件を満たします。

目次

メンバー型

メンバー型 定義
native_handle_type ( optional* ) 実装定義

メンバー関数

ミューテックスを構築する
(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 を起動します。このスレッドは明らかに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

関連項目

共有ミューテックス機能を提供し、タイムアウト付きロックを実装する
(クラス)
移動可能な共有ミューテックス所有権ラッパーを実装する
(クラステンプレート)
移動可能なミューテックス所有権ラッパーを実装する
(クラステンプレート)