#include <thread>
#include <list>
#include <mutex>
#include <algorithm>
#include <stack>
#include <exception>
#include <memory>
#include <iostream>
class hierarchical_mutex {
private:
std::mutex internal_mutex;
unsigned long const hierarchy_value;
unsigned long previous_hierarchy_value;
static thread_local unsigned long this_thread_hierarchy_value;
// 若要对一个mutex加锁,后面mutex的层级必须低于前面已经被锁定的mutex的层级
void check_for_hierarchy_violation() {
if (this_thread_hierarchy_value <= hierarchy_value) {
throw std::logic_error("mutex hierarchy violated");
}
}
void update_hierarchy_value() {
previous_hierarchy_value = this_thread_hierarchy_value;
this_thread_hierarchy_value = hierarchy_value;
}
public:
explicit hierarchical_mutex(unsigned long value) : hierarchy_value(value), previous_hierarchy_value(0) {}
void lock() {
check_for_hierarchy_violation();
internal_mutex.lock();
update_hierarchy_value();
}
void unlock() {
if (this_thread_hierarchy_value != hierarchy_value) {
throw std::logic_error("mutex hierarchy violated");
}
// 复原加锁之前的层级
this_thread_hierarchy_value = previous_hierarchy_value;
internal_mutex.unlock();
}
bool try_lock() {
check_for_hierarchy_violation();
if (!internal_mutex.try_lock()) return false;
update_hierarchy_value();
return true;
}
};
// 初始化当前线程的层级编号为ul的最大值,所以最开始任意的hierarchical_mutex都可以被加锁。
// 由于声明为thread_local 所以每个线程都具备自己的this_thread_hierarchy_value副本
thread_local unsigned long hierarchical_mutex::this_thread_hierarchy_value(ULONG_MAX);
// 使用层级锁防范死锁
// 设置层级 层级越低编号越小
hierarchical_mutex high_level_mutex(10000);
hierarchical_mutex low_level_mutex(5000);
hierarchical_mutex other_mutex(6000);
int do_low_level_stuff() {
std::cout << "0" << std::endl;
return 1;
};
int low_level_func() { // 最底层级
std::lock_guard<hierarchical_mutex> lock(low_level_mutex);
return do_low_level_stuff();
}
int do_high_level_stuff(int some) {
std::cout << some << std::endl;
return some+1;
}
int high_level_func() { // 先对high_level_mutex加锁再对low_level_mutex加锁,符合加锁规则
std::lock_guard<hierarchical_mutex> lock(high_level_mutex);
auto res = do_high_level_stuff(low_level_func());
return res;
}
void thread_a() { // 线程a逻辑正确
high_level_func();
}
void do_other_stuff() {
std::cout << "other" << std::endl;
}
void other_stuff() {
high_level_func();
do_other_stuff();
}
void thread_b() { // 先对中间层级加锁,再调用高层级函数,违反了层级规则,报错。
std::lock_guard<hierarchical_mutex> lock(other_mutex);
other_stuff();
}
int main() {
auto t1 = std::thread(thread_a);
t1.join();
auto t2 = std::thread(thread_b);
t2.join();
return 0;
}
try_lock使用:
lock函数也可以在内部利用该函数,预防死锁。
No comments yet.