Multithreading 为什么会出现死锁?Can';你不能在过程中释放锁吗?
假设一个人试图从银行账户A向银行账户B转账20美元,另一个人同时试图从银行账户B向银行账户A转账30美元。为什么这会导致僵局?每个线程不能执行以下操作: 线程1 获得某人的锁 从支票中提取20美元 解除某人的锁 获得B的锁 B加20美元 松开B的锁 线程2 获得B的锁 从银行提取30美元 松开B的锁 获得某人的锁 在一张支票上加30美元 解除某人的锁Multithreading 为什么会出现死锁?Can';你不能在过程中释放锁吗?,multithreading,deadlock,Multithreading,Deadlock,假设一个人试图从银行账户A向银行账户B转账20美元,另一个人同时试图从银行账户B向银行账户A转账30美元。为什么这会导致僵局?每个线程不能执行以下操作: 线程1 获得某人的锁 从支票中提取20美元 解除某人的锁 获得B的锁 B加20美元 松开B的锁 线程2 获得B的锁 从银行提取30美元 松开B的锁 获得某人的锁 在一张支票上加30美元 解除某人的锁 我知道如果在每个线程的末尾释放资源,这将导致死锁。但是,为什么线程不能在处理完资源后立即释放资源的锁呢?死锁发生在两个资源等待对方释放资源时。当你
我知道如果在每个线程的末尾释放资源,这将导致死锁。但是,为什么线程不能在处理完资源后立即释放资源的锁呢?死锁发生在两个资源等待对方释放资源时。当你穿过一条狭窄的街道时,只有一个人能立刻通过,突然你和另一个人从相反的方向相遇。现在,你们都将等待对方释放资源(即street),直到那时你们都将处于死锁状态 这里是第一个人必须将资金从帐户A转移到B,他必须获得两个帐户才能执行从A点到B点的交易,帐户持有人1正在等待帐户B被释放,但是,帐户持有人2正在等待帐户A被释放,如果你能想象的话,这会形成一个无限循环等待条件(或死锁) 现在考虑上面所提出的,线程1不能释放A的锁,除非事务完成。如果这一切都像你说的那样发生了呢!如果在获得20$后,线程A的锁被释放并扣除20$,并且帐户B的事务由于任何异常而失败,那么现在必须回滚事务,假设帐户A被其他线程占用!您可以看到这可能会导致无限期等待和进一步的数据不一致异常。假设用户向B发送20美元,然后立即停用他的帐户,如果交易失败,这笔钱将流向何处 给定场景的可能解决方案(死锁发生后):
这是我的看法 以下是1线程转账的步骤:
将$20添加到B
,由于某种原因,它失败了。这使得线程回滚,将$20添加回A
。此时,如果锁A
被其他线程占用,将导致无限期等待和一些进一步的问题
这就是为什么它必须保持锁A直到事务完成
假设一个人试图将20美元从银行账户A转到银行账户B,另一个人同时试图将30美元从银行账户B转到银行账户A,为什么会导致僵局
不会的。真正的银行业不是这样运作的
你大概是在通过某种类比或简化版本来论证这个概念
线程1获取A的锁从A的锁中提取$20释放A的锁获取B的锁向B添加$20释放B的锁
这样的事情很可能在真实的代码中完成
需要注意的是,如果出于某种原因,我们无法获得锁B,我们需要再次获得锁A以返还20美元,因为如果我们无法在失败的情况下返还20美元,那么我们就不会有一个交易会完全成功或完全失败,而20美元可能会消失。因此,如果这之后有可能的话无法获得锁B我们可能无法再次获得锁A,这是不可接受的。如果某些东西可能在A和B上获得锁,然后根据它们保护的值做出决定,这也是不可接受的;它们的总和在这一点上是不正确的
另一种可能的方法是订购锁。如果A总是在B之前,那么无论以何种方式转移资金,两个线程都将始终尝试在B之前获取锁A,并且死锁永远不会发生。一个重要的警告是,如果您拥有锁B,并且意识到您也需要锁A,则必须在获取之前释放锁B锁A
另一种可能的方法是,在死锁状态下,一个事务会丢失,其工作会撤消,其锁可能会在重试之前释放,或者可能会在出现异常时释放(或者在出现异常之前重试一定次数)。这在数据库锁定中很常见。但请注意,这需要一些控制代码知道所做的工作,以便可以撤消。这适用于事务数据库,但不适用于大多数多线程程序