多線程 層級鎖
當要同時操作2個對象時,就需要同時鎖定這2個對象,而不是先鎖定一個,然后再鎖定另一個。同時鎖定多個對象的方法:std::lock(對象1.鎖,對象2.鎖...)
但是,有的時候,並不能同時得到所以要鎖定的鎖,必須是先鎖定某個后,再鎖定其他的,這種情況就不能使用std::lock函數了,怎么辦呢,使用有順序的鎖。
額外說明:lock_guard<模板類> ,中模板類的實現。這個模板類只要實現mutex所需要的三個成員函數即可:lock(), unlock(), try_lock()。
例子:lock_guard的模板類hierarchical_mutex
class hierarchical_mutex{
std::mutex mtx;
unsigned long const hcl_val;
unsigned long pre_hcl_val;
static thread_local unsigned long this_hcl_val;
void check_for_hcl_violaction(){
if(this_hcl_val <= hcl_val){
throw std::logic_error("mutex hierarchy violated");
}
}
void update_hierarchy_value(){
pre_hcl_val = this_hcl_val;
this_hcl_val = hcl_val;
}
public:
explicit hierarchical_mutex(unsigned long val):
hcl_val(val), pre_hcl_val(0){}
void lock(){
check_for_hcl_violaction();
mtx.lock();
update_hierarchy_value();
}
void unlock(){
this_hcl_val = pre_hcl_val;
mtx.unlock();
}
bool try_lock(){
check_for_hcl_violaction();
if(!mtx.try_lock())
return false;
update_hierarchy_value();
return true;
}
};
順序鎖的應用例子:當要鎖定時某個鎖時,要先檢查已經上鎖的鎖的序號,如果序號低於現在要鎖的鎖的序號的話就可以鎖定,否則,拋出異常。
我也沒理解鎖的序號的真正含義,只是做個記錄,抄一個例子。。。
#include <mutex>
#include <climits>//ULONG_MAX
#include <thread>
class hierarchical_mutex{
std::mutex mtx;
unsigned long const hcl_val;
unsigned long pre_hcl_val;
static thread_local unsigned long this_hcl_val;
void check_for_hcl_violaction(){
if(this_hcl_val <= hcl_val){
throw std::logic_error("mutex hierarchy violated");
}
}
void update_hierarchy_value(){
pre_hcl_val = this_hcl_val;
this_hcl_val = hcl_val;
}
public:
explicit hierarchical_mutex(unsigned long val):
hcl_val(val), pre_hcl_val(0){}
void lock(){
check_for_hcl_violaction();
mtx.lock();
update_hierarchy_value();
}
void unlock(){
this_hcl_val = pre_hcl_val;
mtx.unlock();
}
bool try_lock(){
check_for_hcl_violaction();
if(!mtx.try_lock())
return false;
update_hierarchy_value();
return true;
}
};
thread_local unsigned long
hierarchical_mutex::this_hcl_val(ULONG_MAX);
hierarchical_mutex high_level_mutex(10000);
hierarchical_mutex low_level_mutex(5000);
int do_low_level_stuff(){
return 1;
}
int low_level_func(){
std::lock_guard<hierarchical_mutex> lk(low_level_mutex);
return do_low_level_stuff();
}
void high_level_stuff(int param){
}
void high_level_func(){
std::lock_guard<hierarchical_mutex> lk(high_level_mutex);
high_level_stuff(low_level_func());
}
void thread_a(){
high_level_func();
}
hierarchical_mutex other_mutex(100);
void do_other_stuff(){
}
void other_stuff(){
high_level_func();
do_other_stuff();
}
void thread_b(){
std::lock_guard<hierarchical_mutex> lk(other_mutex);
other_stuff();
}
int main(){
//鎖定順序合法(因為先鎖的大的,后鎖的小的)
std::thread a(thread_a);
//鎖定順序非法(因為先鎖的小的,后鎖的大的)
std::thread b(thread_b);
a.join();
b.join();
}