zoukankan      html  css  js  c++  java
  • c/c++ 多线程 层级锁

    多线程 层级锁

    当要同时操作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();
    }
    
    

    github源代码

    c/c++ 学习互助QQ群:877684253

    本人微信:xiaoshitou5854

  • 相关阅读:
    【java读书笔记】——java的异常处理
    《C程序猿:从校园到职场》出版预告(4):从“散兵游勇”到“正规部队”
    GIS+=地理信息+行业+大数据——纽约公开11亿条出租车和Uber原始数据下载及分析
    Java第二次作业
    Qt5的插件机制(6)--开发Qt插件时几个重要的宏
    如何获得(读取)web.xml配置文件的參数
    JavaScript、jQuery、HTML5、Node.js实例大全-读书笔记1
    虚幻4Matinee功能 基本概念及简单演示样例(Sequence编辑器)
    Loadrunner Analysis之Web Page Diagnostics
    Linux下Jenkins+git+gradle持续集成环境搭建
  • 原文地址:https://www.cnblogs.com/xiaoshiwang/p/9911600.html
Copyright © 2011-2022 走看看