std:: lock
|
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
ヘッダーで定義
<mutex>
|
||
|
template
<
class
Lockable1,
class
Lockable2,
class
...
LockableN
>
void lock ( Lockable1 & lock1, Lockable2 & lock2, LockableN & ... lockn ) ; |
(C++11以降) | |
指定された
Lockable
オブジェクト
lock1
、
lock2
、
...
、
lockn
をデッドロック回避アルゴリズムを使用してロックし、デッドロックを回避します。
オブジェクトは、未規定の順序で呼び出される
lock
、
try_lock
、および
unlock
によってロックされます。
lock
または
unlock
の呼び出しが例外を発生させた場合、再スローされる前にロックされているすべてのオブジェクトに対して
unlock
が呼び出されます。
目次 |
パラメータ
| lock1, lock2, ... , lockn | - | ロックする Lockable オブジェクト |
戻り値
(なし)
注記
Boostはこの関数のバージョンを提供します これは、イテレータのペアによって定義された Lockable オブジェクトのシーケンスを受け取ります。
std::scoped_lock
はこの関数に対する
RAII
ラッパーを提供し、一般的に
std::lock
への直接呼び出しよりも推奨されます。
例
以下の例では、
std::lock
を使用してデッドロックなしにミューテックスのペアをロックします。
#include <chrono> #include <functional> #include <iostream> #include <mutex> #include <string> #include <thread> #include <vector> struct Employee { Employee(std::string id) : id(id) {} std::string id; std::vector<std::string> lunch_partners; std::mutex m; std::string output() const { std::string ret = "従業員 " + id + " はランチパートナーを持っています: "; for (auto n{lunch_partners.size()}; const auto& partner : lunch_partners) ret += partner + (--n ? ", " : ""); return ret; } }; void send_mail(Employee&, Employee&) { // 時間のかかるメッセージング操作をシミュレート std::this_thread::sleep_for (注:元のテキストはC++の標準ライブラリ関数名であり、HTMLタグや属性も含まれていないため、翻訳対象となる自然言語のテキストが存在しません。C++の専門用語は翻訳しないという指示に従い、そのまま出力しています)(std::chrono::milliseconds (注:指示に従い、HTMLタグ・属性は保持し、C++固有用語は翻訳せず、コードタグ内ではないためテキスト部分のみ翻訳対象としましたが、リンクテキスト全体がC++の型名であるため翻訳を適用していません)(696)); } void assign_lunch_partner(Employee& e1, Employee& e2) { static std::mutex io_mutex; { std::lock_guard<std::mutex> lk(io_mutex); std::cout << e1.id << " および " << e2.id << " はロックを待機中" << std::endl (注:元のテキスト「std::endl」はC++固有の用語であり、HTMLタグ内に含まれているため、翻訳対象外としました。リンク構造と書式は完全に保持されています。); } // std::lockを使用して2つのロックを取得し、デッドロックの心配をせずに // assign_lunch_partnerへの他の呼び出しがデッドロックを引き起こしている { std::lock(e1.m, e2.m); std::lock_guard<std::mutex> lk1(e1.m, std::adopt_lock); std::lock_guard<std::mutex> lk2(e2.m, std::adopt_lock); // 同等のコード(unique_lock が必要な場合、例: 条件変数用) // std::unique_lock<std::mutex> lk1(e1.m, std::defer_lock); // std::unique_lock<std::mutex> lk2(e2.m, std::defer_lock); // std::lock(lk1, lk2); // C++17で利用可能な優れたソリューション // std::scoped_lock lk(e1.m, e2.m); { std::lock_guard<std::mutex> lk(io_mutex); std::cout << e1.id << " および " << e2.id << " ロックを取得しました" << std::endl (注:元のテキスト「std::endl」はC++固有の用語であり、HTMLタグ内に含まれているため、翻訳対象外としました。リンク構造と書式は完全に保持されています。); } e1.lunch_partners.push_back(e2.id); e2.lunch_partners.push_back(e1.id); } send_mail(e1, e2); send_mail(e2, e1); } int main() { Employee alice("Alice"), bob("ボブ"), christina("クリスティーナ"), dave("Dave"); // ランチ割り当てについてユーザーにメール送信するため、並列スレッドで割り当てる // 長時間を要する std::vector<std::thread> threads; threads.emplace_back(assign_lunch_partner, std::ref(alice), std::ref(bob)); threads.emplace_back(assign_lunch_partner, std::ref(christina), std::ref(bob)); threads.emplace_back(assign_lunch_partner, std::ref(christina), std::ref(alice)); threads.emplace_back(assign_lunch_partner, std::ref(dave), std::ref(bob)); for (auto& thread : threads) thread.join(); std::cout << alice.output() << '\n' << bob.output() << '\n' << christina.output() << '\n' << dave.output() << '\n'; }
出力例:
アリスとボブはロックを待っています アリスとボブはロックを取得しました クリスティーナとボブはロックを待っています クリスティーナとボブはロックを取得しました クリスティーナとアリスはロックを待っています デイブとボブはロックを待っています デイブとボブはロックを取得しました クリスティーナとアリスはロックを取得しました 従業員アリスのランチパートナー: ボブ、クリスティーナ 従業員ボブのランチパートナー: アリス、クリスティーナ、デイブ 従業員クリスティーナのランチパートナー: ボブ、アリス 従業員デイブのランチパートナー: ボブ
関連項目
|
(C++11)
|
移動可能なミューテックス所有権ラッパーを実装する
(クラステンプレート) |
|
(C++11)
|
try_lock
の繰り返し呼び出しによりミューテックスの所有権取得を試行する
(関数テンプレート) |
|
(C++17)
|
複数のミューテックスに対するデッドロック回避RAIIラッパー
(クラステンプレート) |