• 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

  • 相关阅读:
    试试SQLServer 2014的内存优化表
    备份数据库的时候设置 BufferCount 选项不正确导致 out of memory 的情况
    SQLSERVER复制优化之一《改变包大小》
    Tomcat配置域名和虚拟文件夹
    BZOJ 1798 [Ahoi2009]Seq 维护序列seq 线段树
    125 Valid Palindrome
    jquery.lazyload.js实现图片懒载入
    hdu 2176 取石子游戏
    算法练习--十进制 二进制互转
    JavaScript学习10:动态载入脚本和样式
  • 原文地址:https://www.cnblogs.com/xiaoshiwang/p/9911600.html
Copyright © 2020-2023  润新知