通过例子理解多线程死锁

多线程死锁

通过一个例子引入死锁的概念。

古代钱庄,通过手写记账记录账户余额,现在客户A用一个账本A,客户B有个账本B,这些账本统一放在文件架上。

现在来了一个客户 需要从A账户装500到B账户。这个时候柜员拿账本的时候会有以下情况:

  1. A,B账本都在文件架上,柜员全部拿走。
  2. 文件架上只有A账本,柜员拿走,并且等待其他柜员把B账本送过来。
  3. 转出账本A与转入账本B都不在文件架上,柜员等待其他柜员送过来。

上面的逻辑可以理解为把A账户作为一个锁,B账户作为一个锁,同时拿到两个锁才可以执行。

引入死锁

有一种场景,当一柜员拿到A账本后,等待其他柜员把B账本送过来。但是另一个柜员此时拿着B账本,等到其他柜员把A账本送过来。此时就造成了死锁。

死锁的定义

一组相互竞争资源的线程因互相等待,导致‘永久’阻塞的现象。

死锁的条件

只有以下4个条件都发生的时候才会出现死锁(注意是都发生)

  1. 互斥:共享资源A和B只能被同一个线程占用。A和B就是上面的账本。
  2. 占有且等待: 线程T1已经取得共享资源A,在等待共享资源B的时候,不会释放贡献支援A.
  3. 不可抢占: 其他线程不可以抢占线程T1占有的资源。
  4. 循环等待:线程T1等待线程T2的资源释放,线程T2等待线程T1的资源释放。

反过来分析就是,破坏其中的一个条件就能避免死锁。

  1. 互斥是锁的特性,不能修改。
  2. 占有且等待:等拿到两把锁的时候再去执行代码。引用上面的例子,就是当A账本和B账本都在文件架上的时候,才把账本交给柜员。 在代码中可以把拿到的锁对象放到list中,校验是否包含。也可以通过自旋的形式去获取两把锁。
  3. 不可抢占锁:可以使用等待唤醒机制。
  4. 破坏循环条件:大致意思就是,两个柜员都去拿A,B账本,我们需要按照一定的顺序去取锁,两个柜员都先去找A账本,在去找B账本。这样就不会出现循环等待。在代码中就是拿到两个锁。把Id小的对象作为第一个锁,另外一个做为第二把锁。
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值