• 一种简单的死锁检测算法


    1.死锁检测

    给定一组线程操作锁的流程,判断是否会发生死锁?

    例如:有两个线程和两个资源,线程对锁的操作如下:

    其中T表示线程id,L表示锁id,S表示操作(1表示获取锁,0表示释放锁)

    T L S

    1 1 1(线程1获取1号锁)

    2 2 2(线程2获取2号锁)

    1 2 1(线程1获取2号锁,保持等待)

    2 1 1(线程2获取1号锁,导致死锁)

    如果最后一次操作换为:2 2 0,就不会死锁.

    问题的关键是如何判断死锁的发生,以上面的例子为例:线程2获取1号锁时,发现1号锁被1号线程占用,那么就要等待线程1释放1号锁,然后再看线程1在等待2号锁,2号锁被2号线程占用,因此1号线程又要等2号线程释放2号锁,这就形成了一个等待环:线程2->线程1->线程2,发生死锁.所以检测死锁的方法就是判断是否存在这种等待的环路.

    对于给定的线程操作锁的序列:vector<vector<int>> tls,判断是否发生死锁要维护3个map,

    map<int, int> lock2thread:锁->线程,标识当前锁被哪个线程占用

    map<int, int> waitedthread2lock:标识当前线程在等待哪个锁

    map<int, vector<int>> thread2locks:标识线程持有的锁.

    伪代码如下(省去了一些更新和查询操作):

    bool DeadLock(vector<vector<int>> &tls) {
      int size = tls.size();
      map<int, int> lock2thread;
      map<int, int> waitedthread2lock;
      map<int, vector<int>> thread2locks; 
      for(int i = 0; i < size; i++) {
        int tid = tls[i][0];
        int lock = tls[i][1];
        int state = tls[i][2];
        if (state == 0) {
          //释放锁,这是一定不会引起死锁的,因此只需要更新3个map就可以了
          //1.从lock2thread中删除key==lock的元素
          lock2thread.erase(lock2thread.find(lock));
          //2.从thread2locks中移除lock
          thread2locks[tid].erase(find(thread2locks[tid].begin(), thread2locks[tid].end(),lock));
          //3.遍历waitedthread2lock,查看哪个线程等待lock
            //3.1如果有线程等待此lock,那么依次更新lock2thread和thread2locks
        } else {
          //说明tid想要获取lock,那么这个操作是可能导致死锁的
          if (lock2thread.find(lock) != lock2thread.end()) {
            //说明该锁已经被占用,那么可能引起死锁
            int nexttid = 0;//当前线程依赖的下一个线程
            int nextlock = lock;
            while(1) {
              nexttid = lock2thread[nextlock];
              if (nexttid == tid) return true;//发生死锁
              //查看nexttid在等待哪个资源
              if (waitedthread2lock.find(nexttid) != waitedthread2lock.end()) {
                nextlock = waitedthread2lock[nexttid];
              } else {
                //说明没有环路,不发生死锁
                更新waitedthread2lock;
                break;
              }
            }
          } else {
            //说明lock空闲,直接获取
            更新lock2thread和thread2locks;
            }
        }
      }
    }

     2.死锁预防:银行家算法

    思路很简单,只有当资源池中有充足的资源时才将资源分配给进程,否则便认为可能存在死锁的风险.

    具体可参考这篇简单明了的文章:https://zhuanlan.zhihu.com/p/59533950

  • 相关阅读:
    [LeetCode]Word Break
    [LeetCode]singleNumber
    [LeetCode]Palindrome
    新浪博客无法访问
    C++基础之顺序容器
    C++基础之IO类
    [LeetCode]Restore IP Addresses
    [LeetCode]Maximal Rectangle
    [LeetCode]Reverse Linked List II
    ACM 树形数组
  • 原文地址:https://www.cnblogs.com/deepllz/p/11533860.html
Copyright © 2020-2023  润新知