Bob*_*toe 67
使用传统示例考虑竞争条件.假设您和一位朋友拥有同一银行账户的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
Run Code Online (Sandbox Code Playgroud)
在两个事务完成后,使用此时间轴(如果您不使用任何类型的锁定机制,这是可能的),该帐户有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)
Run Code Online (Sandbox Code Playgroud)
您可以看到在时间7发生死锁,因为T2尝试获取锁定,x但T1已经保持锁定x但是它正在等待锁定y,T2保持.
这很糟糕.您可以将此图转换为依赖图,您将看到有一个循环.这里的问题是x和y是可以一起修改的资源.
防止多种锁定对象(资源)出现这种死锁问题的一种方法是引入排序.你看,前面的例子中,T1锁定x,然后y,但T2锁定y,然后x.如果这两个事务都遵守一些说明" x应始终锁定y"的排序规则,则不会发生此问题.(您可以在考虑此规则的情况下更改上一个示例,并且不会发生死锁).
这些是微不足道的例子,我真的只是使用了你可能已经看过的例子,如果你已经采取了任何类型的本科课程.实际上,解决死锁问题可能比这更难,因为您往往拥有多个资源和几个事务交互.
希望这有点帮助.与往常一样,使用维基百科作为CS概念的起点:
http://en.wikipedia.org/wiki/Deadlock
http://en.wikipedia.org/wiki/Race_condition
小智 14
死锁是两个(或更多)线程相互阻塞的时候.通常这与尝试获取共享资源的线程有关.例如,如果线程T1和T2需要同时获取资源A和B以便完成其工作.如果T1获得资源A,然后T2获得资源B,那么T1可等待资源B,而T2在等待资源A在这种情况下,两个线程将无限期地等待被其他线程持有的资源.据说这些线程已陷入僵局.
当两个线程以负面(错误)方式交互时,会发生竞争条件,具体取决于执行不同指令的确切顺序.如果一个线程设置一个全局变量,例如,然后第二个线程读取和修改了全局变量,并在第一个线程读取变量,因为变量意外更改的第一个线程可能会遇到的错误.
死锁:
种族/种族条件:
在编码中,我们需要避免竞争和死锁情况。
我认为你的意思是"竞争条件"而不是"围绕条件竞赛"(我听说过那个词......)
基本上,死锁是线程A在对资源Y持有锁定时等待资源X的情况,并且线程B在对资源X持有锁定时等待资源Y.线程阻塞等待彼此释放它们锁.
此问题的解决方案(通常)是确保您在所有线程中以相同顺序对所有资源进行锁定.例如,如果您始终在资源Y 之前锁定资源X ,那么我的示例永远不会导致死锁.
竞争条件是指您依赖于按特定顺序发生的特定事件序列,但如果另一个线程同时运行,则可能会混乱.例如,要将新节点插入链接列表,您需要修改列表头,通常是这样的:
newNode->next = listHead;
listHead = newNode;
Run Code Online (Sandbox Code Playgroud)
但是如果两个线程同时执行此操作,那么您可能会遇到这样的情况:
Thread A Thread B
newNode1->next = listHead
newNode2->next = listHead
listHead = newNode2
listHead = newNode1
Run Code Online (Sandbox Code Playgroud)
如果发生这种情况,那么线程B对列表的修改将会丢失,因为线程A会覆盖它.它可能更糟糕,取决于具体情况,但这是它的基础.
此问题的解决方案通常是确保您包含正确的锁定机制(例如,在您想要修改链接列表的任何时候取出锁定,以便一次只有一个线程正在修改它).