最終更新日時:
が更新

履歴 編集

class template
<mutex>

std::unique_lock(C++11)

namespace std {
  template <class Mutex>
  class unique_lock;
}

概要

unique_lockは、ミューテックスのlock()unlock()処理を、コンストラクタとデストラクタで確実に実行するためのクラスである。

このクラスは通常、メンバ変数もしくはグローバル変数としてもつミューテックスオブジェクトに対し、関数内の先頭でlock()、関数を抜ける際にunlock()を確実に呼び出すために使用される。この手法は、Scoped Locking Patternとして知られている。

テンプレートパラメータMutexは、lock()unlock()メンバ関数を持つあらゆるミューテックスクラスを扱うためのものである。ミューテックス型をパラメータ化するScoped Locking手法は、Strategized Locking Patternとして知られている。

シンプルな機能しか提供しないlock_guardクラスとの違いとして、以下の拡張機能を持つ:

  • コンストラクタでロックを取得せず、あとからロックを取得できる(defer_lock)
  • コンストラクタでのロック取得に、lock()ではなくtry_lock()を使用できる(try_to_lock)
  • ミューテックスの所有権を移動・交換(swap)・放棄(release)できる
  • 任意のタイミングで所有ミューテックスのロック操作を呼び出せる

また条件変数std::condition_variableオブジェクトと組み合わせて利用できるのは、std::unique_lock<std::mutex>型のオブジェクトに限定されている。

メンバ関数

名前 説明 対応バージョン
(constructor) コンストラクタ C++11
(destructor) デストラクタ C++11
operator= 代入演算子 C++11
lock ロックを取得する C++11
try_lock ロックの取得を試みる C++11
try_lock_for タイムアウトする相対時間を指定してロックの取得を試みる C++11
try_lock_until タイムアウトする絶対時間を指定してロックの取得を試みる C++11
unlock ロックを手放す C++11
swap 他のunique_lockオブジェクトと値を入れ替える C++11
release ミューテックスの所有権を放棄する C++11
owns_lock ロックを取得しているかを判定する C++11
operator bool ロックを取得しているかを判定する C++11
mutex 所有しているミューテックスオブジェクトを取得する C++11

メンバ型

名前 説明 対応バージョン
mutex_type ミューテックス型Mutex C++11

非メンバ関数

名前 説明 対応バージョン
swap 2つのunique_lockオブジェクトを入れ替える C++11

#include <iostream>
#include <thread>
#include <mutex>
#include <vector>

// std::coutへのアクセスを排他的にする
std::mutex print_mtx_;
void safe_print(int x)
{
  std::lock_guard<std::mutex> lock(print_mtx_);
  std::cout << x << std::endl;
}

class X {
  std::mutex mtx_;
  std::vector<int> data_;
public:
  std::unique_lock<std::mutex> get_lock()
  {
    return std::unique_lock<std::mutex>(mtx_); // ロックを取得する
  }

  // vectorオブジェクトへのアクセスを排他的にする
  void add_value(int value)
  {
    std::unique_lock<std::mutex> lk = get_lock(); // ロックされたunique_lockを受け取る

    data_.push_back(value);
  } // ロックを手放す(unique_lockのデストラクタ)

  void print()
  {
    std::unique_lock<std::mutex> lk = get_lock();

    for (int x : data_) {
      safe_print(x);
    }
  }
};

int main()
{
  X x;

  std::thread t1([&x]{ x.add_value(1); });
  std::thread t2([&x]{ x.add_value(2); });

  t1.join();
  t2.join();

  x.print();
}

出力例

2
1

バージョン

言語

  • C++11

処理系

関連項目

  • shared_lock : 共有ミューテックスを自動的に手放す