在编程术语中,死锁和围绕条件的竞争有什么区别?
5 回答
考虑使用传统示例的竞争条件。假设您和一个朋友拥有同一个银行账户的 ATM 卡。现在假设帐户中有 100 美元。考虑一下当您尝试提取 10 美元而您的朋友同时尝试提取 50 美元时会发生什么。
想想必须发生的事情。ATM 机必须接受您的输入,读取您帐户中当前的内容,然后修改金额。请注意,在编程术语中,赋值语句是一个多步骤的过程。
因此,将您的交易标记为 T1(您提取 10 美元)和 T2(您的朋友提取 50 美元)。现在,下面左边的数字代表时间步长。
T1 T2
---------------- ------------------------
1. Read Acct ($100)
2. Read Acct ($100)
3. Write New Amt ($90)
4. Write New Amt ($50)
5. End
6. End
两笔交易完成后,使用此时间线(如果您不使用任何类型的锁定机制),账户中就有 50 美元。这比它应该多出 10 美元(您的交易将永远丢失,但您仍然有钱)。
这就是所谓的竞争条件。您想要的是使事务可序列化,也就是说,无论您如何交错各个指令执行,最终结果都将与某些串行调度完全相同(这意味着您一个接一个地运行它们而没有交错)相同的交易。再次,解决方案是引入锁定;但是不正确的锁定会导致死锁。
当共享资源发生冲突时,就会发生死锁。这有点像 Catch-22。
T1 T2
------- --------
1. Lock(x)
2. Lock(y)
3. Write x=1
4. Write y=19
5. Lock(y)
6. Write y=x+1
7. Lock(x)
8. Write x=y+2
9. Unlock(x)
10. Unlock(x)
11. Unlock(y)
12. Unlock(y)
您可以看到在时间 7 发生了死锁,因为 T2 尝试获取锁,x
但 T1 已经持有锁,x
但它正在等待y
T2 持有的锁。
这不好。你可以把这个图变成一个依赖图,你会看到有一个循环。这里的问题是 x 和 y 是可以一起修改的资源。
防止这种带有多个锁对象(资源)的死锁问题的一种方法是引入排序。您会看到,在前面的示例中,T1 被锁定x
,然后y
T2 被锁定y
,然后x
。如果这里的两个事务都遵循一些“x
应始终在之前锁定y
”的排序规则,则不会发生此问题。(您可以根据此规则更改前面的示例,并且不会出现死锁)。
这些都是微不足道的例子,如果你参加过任何类型的本科课程,我只是使用了你可能已经看过的例子。实际上,解决死锁问题可能比这要困难得多,因为您往往有多个资源和几个交互的事务。
希望这会有所帮助。与往常一样,使用 Wikipedia 作为 CS 概念的起点:
死锁是当两个(或更多)线程相互阻塞时。通常这与试图获取共享资源的线程有关。例如,如果线程 T1 和 T2 需要同时获取资源 A 和 B 才能完成工作。如果 T1 获取资源 A,然后 T2 获取资源 B,则 T1 可能正在等待资源 B,而 T2 正在等待资源 A。在这种情况下,两个线程将无限期地等待另一个线程持有的资源。这些线程被称为死锁。
当两个线程根据执行不同指令的确切顺序以否定(错误)方式交互时,就会出现竞争条件。例如,如果一个线程设置了一个全局变量,然后第二个线程读取并修改了该全局变量,而第一个线程读取了该变量,则第一个线程可能会遇到错误,因为该变量已意外更改。
死锁:
- 当2 个或更多线程相互等待以无限时间释放资源时,就会发生这种情况。
- 在这种情况下,线程处于阻塞状态并且不执行。
比赛/比赛条件:
- 当2 个或更多线程并行运行但如果所有操作都按顺序完成时最终给出错误且不等效的结果时,就会发生这种情况。
- 这里所有的线程都运行并在那里执行操作。
在编码中,我们需要避免竞争和死锁情况。
我假设您的意思是“竞争条件”而不是“围绕条件竞争”(我听说过这个词......)
基本上,死锁是这样一种情况:线程 A 在等待资源 X 的同时持有资源 Y 的锁,线程 B 正在等待资源 Y 的同时持有资源 X 的锁。线程阻塞等待对方释放它们的锁。锁。
这个问题的解决方案是(通常)确保您在所有线程中以相同的顺序锁定所有资源。例如,如果您总是在资源 Y之前锁定资源 X,那么我的示例永远不会导致死锁。
竞争条件是指您依赖以特定顺序发生的特定事件序列,但如果另一个线程同时运行,则可能会搞砸。例如,要将新节点插入到链表中,您需要修改链表头,通常是这样的:
newNode->next = listHead;
listHead = newNode;
但是,如果两个线程同时执行此操作,那么您可能会遇到这样的情况:
Thread A Thread B
newNode1->next = listHead
newNode2->next = listHead
listHead = newNode2
listHead = newNode1
如果发生这种情况,那么线程 B 对列表的修改将丢失,因为线程 A 会覆盖它。根据具体情况,情况可能会更糟,但这是基本情况。
此问题的解决方案通常是确保您包含正确的锁定机制(例如,在您想要修改链表的任何时候取出锁,以便一次只有一个线程在修改它)。
如果你没有锁定共享资源并且被多个线程访问,那么它被称为“竞争条件”,第二种情况如果你锁定了资源并且对共享资源的访问顺序没有正确定义,那么线程可能会持续很长时间等待资源使用然后这是“死锁”的情况