一 类型
1. std::defer_lock_t 、 std::try_to_lock_t 和 std::adopt_lock_t 是用于为 std::lock_guard(C++11) 、 std::scoped_lock(C++14) 、 std::unique_lock(C++11) 和 std::shared_lock(C++17) 指定锁定策略的空结构体标签类型。
2. std::defer_lock 、 std::try_to_lock 和 std::adopt_lock 分别是 std::defer_lock_t 、 std::try_to_lock_t 和 std::adopt_lock_t 的实例。
它们用于为 std::lock_guard 、 std::unique_lock 及 std::shared_lock 指定锁定策略。
二 含义
defer_lock_t 不获得互斥的所有权
try_to_lock_t 尝试获得互斥的所有权而不阻塞
adopt_lock_t 假设调用方线程已拥有互斥的所有权
三 构造函数
1. lock_guard
explicit lock_guard( mutex_type& m ); (1)(C++11 起)
lock_guard( mutex_type& m, std::adopt_lock_t t ); (2)(C++11 起)
lock_guard( const lock_guard& ) = delete; (3)(C++11 起)
2. unique_lock
unique_lock() noexcept;(1) (since C++11)
unique_lock( unique_lock&& other ) noexcept;(2)(since C++11)
explicit unique_lock( mutex_type& m );(3)(since C++11)
unique_lock( mutex_type& m, std::defer_lock_t t ) noexcept;(4)(since C++11)
unique_lock( mutex_type& m, std::try_to_lock_t t );(5)(since C++11)
unique_lock( mutex_type& m, std::adopt_lock_t t );(6)(since C++11)
template< class Rep, class Period >
unique_lock( mutex_type& m,const std::chrono::duration<Rep,Period>& timeout_duration );(7)(since C++11)
template< class Clock, class Duration >
unique_lock( mutex_type& m,const std::chrono::time_point<Clock,Duration>& timeout_time );(8)(since C++11)
3. scoped_lock
explicit scoped_lock( MutexTypes&... m ); (1)(C++17 起)
scoped_lock( std::adopt_lock_t, MutexTypes&... m ); (2)(C++17 起)
scoped_lock( const scoped_lock& ) = delete; (3)(C++17 起)
4. shared_lock
shared_lock() noexcept;(1)(C++14 起)
shared_lock( shared_lock&& other ) noexcept;(2)(C++14 起)
explicit shared_lock( mutex_type& m );(3)(C++14 起)
shared_lock( mutex_type& m, std::defer_lock_t t ) noexcept;(4)(C++14 起)
shared_lock( mutex_type& m, std::try_to_lock_t t );(5)(C++14 起)
shared_lock( mutex_type& m, std::adopt_lock_t t );(6)(C++14 起)
template< class Rep, class Period >
shared_lock( mutex_type& m,
const std::chrono::duration<Rep,Period>& timeout_duration );(7)(C++14 起)
template< class Clock, class Duration >
shared_lock( mutex_type& m,
const std::chrono::time_point<Clock,Duration>& timeout_time );(8)(C++14 起)
四 Demo
#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 = "Employee " + id + " has lunch partners: ";
for (const auto& partner : lunch_partners)
ret += partner + " ";
return ret;
}
};
void send_mail(Employee&, Employee&) {
// simulate a time-consuming messaging operation
std::this_thread::sleep_for(std::chrono::seconds(1));
}
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 << " and " << e2.id << " are waiting for locks"
<< std::endl;
}
{
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);
// 等效代码1
// 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);
// 等效代码2
// std::scoped_lock lock(e1.m, e2.m);
{
std::lock_guard<std::mutex> lk(io_mutex);
std::cout << e1.id << " and " << e2.id << " got locks" << std::endl;
}
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("bob"), christina("christina"), dave("dave");
// assign in parallel threads because mailing users about lunch assignments
// takes a long time
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';
std::cin.get();
return 0;
}
结果:
alice and bob are waiting for locks
christina and bob are waiting for locks
alice and bob got locks
christina and alice are waiting for locks
christina and alice got locks
dave and bob are waiting for locks
christina and bob got locks
dave and bob got locks
Employee alice has lunch partners: bob christina
Employee bob has lunch partners: alice christina dave
Employee christina has lunch partners: alice bob
Employee dave has lunch partners: bob
五 参考