「std::lock」の版間の差分

提供: C++入門
移動: 案内検索
(ページの作成:「std::lock とは、C++のマルチスレッドプログラムで複数のmutexをロックするときにデッドロックを防ぐために、遅延ロック(defe...」)
 
(相違点なし)

2013年12月29日 (日) 21:47時点における最新版

std::lock とは、C++のマルチスレッドプログラムで複数のmutexをロックするときにデッドロックを防ぐために、遅延ロック(deferred locking)を実現するために使用します。

読み方

std::lock
えすてぃーでぃー ろっく

概要

マルチスレッドプログラムで複数のmutexのロックが必要なケースがあります。このとき、ロックの順番を間違えると、デッドロックが発生します。デットロックとは、2つのスレッドが逆の順番にロックしようとしたとき、それぞれがもっているロックが解除されるのをお互いに待ち続けるような状況に陥ることです。

複数のロックをまとめて行うために、C++11では、std::lockで複数のmutexをまとめてロックする汎用の関数を提供しています。

複数のmutexをロックする例

ソースコード std_lock1.cpp

#include <iostream>
#include <thread>
#include <exception>
#include <mutex>
using namespace std;
struct Mutex {
        std::mutex      m;
        int             i;
        Mutex(): i(0){}
};
 
void
do_worker1 (Mutex& m1, Mutex& m2) {
        std::cout << __PRETTY_FUNCTION__ << std::endl;
 
        //ここではロックしない
        std::unique_lock<std::mutex> ul1(m1.m, std::defer_lock);
        std::unique_lock<std::mutex> ul2(m2.m, std::defer_lock);
 
        //ここでロックする
        std::lock(ul1, ul2);
 
        std::cout << __PRETTY_FUNCTION__ << std::endl;
        m1.i++;
        m2.i++;
        // mutex unlocked !
}
 
int
main (int argc, char *argv[]) {
        try {
                Mutex m1,m2;
                std::thread t1(do_worker1, std::ref(m1), std::ref(m2) );
                std::thread t2(do_worker1, std::ref(m1), std::ref(m2) );
                t1.join();
                t2.join();
        } catch (std::exception &ex) {
                std::cerr << ex.what() << std::endl;
        }
        return (0);
}

コンパイル

g++49 -std=c++11 -I/usr/local/lib/gcc49/include/c++/ \
-Wl,-rpath=/usr/local/lib/gcc49  -pthread std_lock1.cpp -o std_lock1

実行例

% ./std_lock1
void do_worker1(Mutex&, Mutex&)void do_worker1(Mutex&, Mutex&)
 
void do_worker1(Mutex&, Mutex&)
void do_worker1(Mutex&, Mutex&)

関連項目

mutex
mutexの種類 説明
std::mutex 非再帰的mutex
std::recursive_mutex 再帰的mutext
std::timed_mutex ロック関数でタイムアウトが可能な非再帰的mutex
std::recursive_timed_mutex ロック関数でタイムアウトが可能な再帰的mutex

ロッククラステンプレート

std::thread メンバ関数
関数 説明
メンバ関数
std::thread::thread コンストラクタ。threadオブジェクトを作成します。
std::thread::~thread スレッドがjoinかdetachされている必要があります。スレッドオブジェクトを破棄します。
std::thread::operator= スレッドオブジェクトをmoveします。
オブザーバー
std::thread::joinable スレッドが合流可能であるかチェックします。
std::thread::get_id スレッドのIDを返します。
std::thread::native_handle スレッドハンドルを返します。
std::thread::hardware_concurrency 実装によってサポートされる同時スレッド数を返します。
操作
std::thread::join スレッドの終了を待ちます。
std::thread::detach スレッドハンドルから独立して実行するスレッドを許可します。
std::thread::swap スワップ
非メンバ関数
std::swap スワップ
カレントスレッドの管理
std::this_thread::yield_id 処理系に再スケジュールの機会を与えます。
std::this_thread::get_id スレッドIDを返します。
std::this_thread::sleep_for 指定した時間、現在のスレッドの実行を停止します。
std::this_thread::sleep_until 指定した時刻まで、現在のスレッドの実行を停止します。