zoukankan      html  css  js  c++  java
  • 避免死锁的一些注意事项

    1. 避免嵌套锁, 如果每个线程都只占有一个锁, 则可以很大程度上避免死锁。
    其死锁的情况是, 线程 1 依次获得 A 对象和 B 对象的锁, 然后决定等另一个线程的信号再继续, 从而先释放了 B 对象的的锁。
    可是线程 2 需要同时拥有对象 A 和对象 B 的锁才能向线程 1 发信号。
    从而导致, 线程 2 因无法获得对象 A 上的锁, 因而阻塞, 等待线程 1 释放对象 A 上的锁。 而同时线程 1 也一直阻塞, 等待线程 2 的信号, 因此不会释放对象 A 的锁。

    2. 用固定的顺序获取锁
    如果非要同时拥有多个锁, 同时无法拥有单个的锁, 那么最好的处理方式是以固定的顺序得到他们。典型的情况是在一个链表的结构中, 如果要取得节点 B 的锁, 那么需要先取得节点 A 的锁, 接着取得节点 C 的锁。

    3. 设置优先级
    当多个锁存在时, 设立优先级是个好主意,这样可以避免低优先级的 mutex 会先于高优先级的拥有锁。例如以下代码:

    hierarchical_mutex high_level_mutex(10000);
    hierarchical_mutex  low_level_mutex(5000);
    
    int do_low_level_stuff();
    
    int low_level_func()
    {
        lock_guard<hierarchical_mutex> lk(low_level_mutex);
        return do_low_level_stuff();
    }
    
    void high_level_stuff(int some_param);
    
    void high_level_func()
    {
        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_levek_func();
        do_other_stuff();
    }
    
    void thread_b()
    {
        lock_guard<hierarchical_mutex> lk(other_mutex);
        other_stuff();
    }

    其中, thread_a 就会成功, 而 therad_b 就会运行出错。
    为啥呢?
    因为它首先会拥有 other_mutex 的锁,other_mutex 的优先级只有 100, 却在  high_level_mutex 前得到锁, 这违反了优先级, 所以 hierarchical_mutex 会报错并抛出一个异常, 然后退出程序。
    上文中提到的 hierarchical_mutex 并不是标准库的一部分, 但是可以很容易的实现:

    class hierarchical_mutex
    {
        mutex                                   internal_mutex;
        unsigned long const                     hierarchy_value;
        unsigned                                previous_hierarchy_value;
        static  thread_local unsigned long    this_thread_hierarchy_value;
        
        // second mutex must now be less than 
        //that of the mutex already held 
      //in order for the check to pass
    void check_for_hierarcy_violation() { if(this_thread_hierarchy_value <= hierarchy_value){ throw std::logic_error("mutex hierarchical 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_hierarcy_violation(); internal_mutex.lock(); update_hierarchy_value(); } void unlock() { this_thread_hierarchy_value = previous_hierarchy_value; internal_mutex.unlock(); } bool try_lock() { check_for_hierarcy_violation(); if(!internal_mutex.try_lock()){ return false; } update_hierarchy_value(); return true; } }; // initialized to the maximum value, // so initially any mutex can be locked thread_local unsigned long hierarchical_mutex::this_thread_hierarchy_value(ULONG_MAX);
  • 相关阅读:
    MagicZoom bug-Strict Standards: Only variables should be assigned by reference Error
    Web大文件(夹)上传(断点续传)控件-Xproer.HttpUploader6
    在PHP中,通过filesize函数可以取得文件的大小,文件大小是以字节数表示的。如果要转换文件大小的单位,可以自己定义函数来实现。
    PHP正则匹配6到16位字符组合(且只能为数字、字母、下划线)
    Windows下PHP版本选取
    简单配置nginx使之支持pathinfo
    PHP如何关闭notice级别的错误提示
    php开启pathinfo 模式
    php 5.3新增的闭包语法介绍function() use() {}
    Object.prototype.toString.call() 区分对象类型
  • 原文地址:https://www.cnblogs.com/wuOverflow/p/4298804.html
Copyright © 2011-2022 走看看