最終更新日時: 2026年03月23日 21時31分23秒 (JST)
Raclamusi が更新

履歴 編集

class
<shared_mutex>

# std::shared_mutex(C++17)

    namespace std {
      class shared_mutex;
    }

## 概要

`shared_mutex`クラスは、Readers-writer lockパターンをサポートするミューテックスクラスである。

このパターンは、「複数のユーザーによる読み込みと、単一ユーザーによる書き込み」の排他制御を効率的に行う、というものである。

このミューテックスクラスのロック取得方法は2種類ある。

- `lock()`／`unlock()`メンバ関数：書き込み用のロックを取得する
- `lock_shared()`／`unlock_shared()`メンバ関数：読み込み用のロックを取得する

このクラスは、デストラクタで自動的にロックを手放すことはしない。そのため、以下の補助クラスを使用して、デストラクタで自動的にロックを手放す。

- `lock_guard`クラス／`unique_lock`クラス：書き込み用のロックを自動的に手放す
- `shared_lock`：読み込み用のロックを自動的に手放す

## 備考

- このクラスは現状、書き込みロックと読み込みロックについてのスケジューリング戦略を規定せず、カスタマイズもできない。そのため、書き込みロックがなかなか取得できない、読み込みロックがなかなか取得できないというスタベーションの問題が発生した場合に、ユーザーの状況に合わせて戦略を変更することができない。POSIXのReaders-writer lockの実装では、スケジューリングのオプションを指定できる
  - `pthread_rwlockattr_setkind_np()`

## メンバ関数

### 構築・破棄

名前 | 説明 | 対応バージョン
--- | --- | ---
`(constructor)` | コンストラクタ | C++17
`(destructor)` | デストラクタ | C++17
`operator=(const shared_mutex&) = delete;` | 代入演算子 | C++17

### 排他の所有権

名前 | 説明 | 対応バージョン
--- | --- | ---
`lock` | 排他ロックを取得する | C++17
`try_lock` | 排他ロックの取得を試みる | C++17
`unlock` | 排他ロックを手放す | C++17

### 共有の所有権

名前 | 説明 | 対応バージョン
--- | --- | ---
`lock_shared` | 共有ロックを取得する | C++17
`try_lock_shared` | 共有ロックの取得を試みる | C++17
`unlock_shared` | 共有ロックを手放す | C++17

## 例

    #include <iostream>
    #include <thread>
    #include <mutex>
    #include <shared_mutex>
    #include <chrono>

    std::mutex print_mtx;
    void print_value(int x)
    {
      std::lock_guard<std::mutex> lock(print_mtx);
      std::cout << x << std::endl;
    }

    class X {
      std::shared_mutex mtx_;
      int count_ = 0;
    public:
      // 書き込み側：カウンタを加算する
      void writer()
      {
        std::lock_guard<std::shared_mutex> lock(mtx_);
        ++count_;
      }

      // 読み込み側：カウンタの値を読む
      void reader()
      {
        int local_count;
        {
          std::shared_lock<std::shared_mutex> lock(mtx_);
          local_count = count_;
        } // 共有ロックをここで手放す
        print_value(local_count);
      }
    };

    X obj;
    void writer_thread()
    {
      for (int i = 0; i < 3; ++i) {
        std::this_thread::sleep_for(std::chrono::milliseconds(1));
        obj.writer();
      }
    }

    void reader_thread()
    {
      for (int i = 0; i < 10; ++i) {
        std::this_thread::sleep_for(std::chrono::milliseconds(1));
        obj.reader();
      }
    }

    int main()
    {
      // 書き込みユーザー1人
      // 読み込みユーザー3人
      std::thread writer1(writer_thread);
      std::thread reader1(reader_thread);
      std::thread reader2(reader_thread);
      std::thread reader3(reader_thread);

      writer1.join();
      reader1.join();
      reader2.join();
      reader3.join();
    }

### 出力例

    1
    1
    1
    2
    2
    2
    3
    3
    3
    3
    3
    3
    3
    3
    3
    3
    3
    3
    3
    3
    3
    3
    3
    3
    3
    3
    3
    3
    3
    3

## バージョン

### 言語

- C++17

### 処理系

- Clang: 3.7.1 ✅
- GCC: 6.3 ✅
- ICC: ??
- Visual C++: ??

## 関連項目

- `std::shared_timed_mutex`

## 参照

- Readers–writer lock - Wikipedia
- N4508: A proposal to add `shared_mutex` (untimed)