ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

第一部分:并发理论基础05->死锁了怎么办

2021-06-30 16:34:57  阅读:165  来源: 互联网

标签:target synchronized 05 并发 死锁 balance 账本 amt


1.3个人互相转账

3个人互相转账,串行

2.账本

  1. 文件架上有转出账本+转入账本,同时拿走
  2. 文件架上只有转出账本,柜员就先把文件架上的转出账本拿到手里,同时等着另一个账本送回来。
  3. 文件架上一个账本都没有,等两个账本都回来。

3.明细


class Account {
  private int balance;
  // 转账
  void transfer(Account target, int amt){
    // 锁定转出账户
    synchronized(this) {              
      // 锁定转入账户
      synchronized(target) {           
        if (this.balance > amt) {
          this.balance -= amt;
          target.balance += amt;
        }
      }
    }
  } 
}

4.如何预防死锁

出现死锁,以下4个条件

  1. 互斥,共享资源x和y只能被一个线程占用
  2. 占有且等待,线程T1已经取得共享资源x,在等待共享资源y的时候,不释放共享资源x
  3. 不可抢占,其他线程不能强行占用T1占有的资源
  4. 循环等待,线程T1等待T2占有的资源,T2等待T1占有的资源。循环等待

破坏其中任意一个条件,就可以避免死锁发生

  1. 占有且等待,一次性申请所有资源,就不存在等待了
  2. 不可抢占条件,占用资源线程进一步申请其他资源时,申请不到,可以主动释放它占有的资源,不可抢占条件就破坏了
  3. 循环等待条件,按序申请资源。

5.预防死锁的案例

  1. 破坏占用且等待条件
    一次性申请所有资源,就同时拿到转入账本和转出账本的概念

class Allocator {
  private List<Object> als =
    new ArrayList<>();
  // 一次性申请所有资源
  synchronized boolean apply(
    Object from, Object to){
    if(als.contains(from) ||
         als.contains(to)){
      return false;  
    } else {
      als.add(from);
      als.add(to);  
    }
    return true;
  }
  // 归还资源
  synchronized void free(
    Object from, Object to){
    als.remove(from);
    als.remove(to);
  }
}

class Account {
  // actr应该为单例
  private Allocator actr;
  private int balance;
  // 转账
  void transfer(Account target, int amt){
    // 一次性申请转出账户和转入账户,直到成功
    while(!actr.apply(this, target))
      ;
    try{
      // 锁定转出账户
      synchronized(this){              
        // 锁定转入账户
        synchronized(target){           
          if (this.balance > amt){
            this.balance -= amt;
            target.balance += amt;
          }
        }
      }
    } finally {
      actr.free(this, target)
    }
  } 
}
  1. 破坏不可抢占条件
    主动释放它占用的资源,synchronized实现不了,但是Lock可以实现

  2. 破坏循环等待条件
    需要对资源进行排序,按序申请资源。


class Account {
  private int id;
  private int balance;
  // 转账
  void transfer(Account target, int amt){
    Account left = this        ①
    Account right = target;    ②
    if (this.id > target.id) { ③
      left = target;           ④
      right = this;            ⑤
    }                          ⑥
    // 锁定序号小的账户
    synchronized(left){
      // 锁定序号大的账户
      synchronized(right){ 
        if (this.balance > amt){
          this.balance -= amt;
          target.balance += amt;
        }
      }
    }
  } 
}

6.总结

细粒度锁,锁多个资源,注意死锁问题
破坏死锁条件中的任意一个,就不会出现死锁

标签:target,synchronized,05,并发,死锁,balance,账本,amt
来源: https://www.cnblogs.com/PythonOrg/p/14955101.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有