【问题标题】:Difference between racearound condition and deadlock竞速条件和死锁的区别
【发布时间】:2010-06-28 04:37:17
【问题描述】:

在编程术语中,死锁和条件竞争有什么区别?

【问题讨论】:

    标签: multithreading deadlock race-condition


    【解决方案1】:

    使用传统示例考虑竞争条件。假设您和一个朋友拥有同一个银行账户的 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 美元(您的交易将永远丢失,但您仍有钱)。

    这是一个所谓的竞争条件。您想要的是使事务可序列化,也就是说,无论您如何交错各个指令执行,最终结果都将与 some 串行调度完全相同(意味着您一个接一个地运行它们而没有交错)相同的事务。再次,解决方案是引入锁定;但是不正确的锁定会导致死锁。

    当共享资源发生冲突时会发生死锁。这有点像 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 上的锁,但它正在等待 T2 持有的 y 的锁。

    这太糟糕了。你可以把这个图变成一个依赖图,你会看到有一个循环。这里的问题是 x 和 y 是可以一起修改的资源。

    防止这种与多个锁对象(资源)有关的死锁问题的一种方法是引入排序。您会看到,在前面的示例中,T1 锁定 x,然后锁定 y,但 T2 锁定 y,然后锁定 x。如果此处的两个事务都遵循某些排序规则,即“x 应始终在y 之前锁定”,则不会发生此问题。 (您可以根据此规则更改前面的示例,并且不会出现死锁)。

    这些都是琐碎的例子,如果你参加过任何类型的本科课程,我只是使用了你可能已经看过的例子。实际上,解决死锁问题可能比这要困难得多,因为您往往有多个资源和多个事务交互。

    希望这会有所帮助。与往常一样,使用 Wikipedia 作为 CS 概念的起点:

    http://en.wikipedia.org/wiki/Deadlock

    http://en.wikipedia.org/wiki/Race_condition

    【讨论】:

    • 我相信死锁发生在第 5 行本身,因为 y 已经被 T2 锁定。
    【解决方案2】:

    死锁是指两个(或更多)线程相互阻塞。通常这与试图获取共享资源的线程有关。例如,如果线程 T1 和 T2 需要同时获取资源 A 和 B 才能完成工作。如果 T1 获取资源 A,然后 T2 获取资源 B,则 T1 可能正在等待资源 B,而 T2 正在等待资源 A。在这种情况下,两个线程将无限期地等待另一个线程持有的资源。这些线程被称为死锁。

    当两个线程根据执行不同指令的确切顺序以否定(错误)方式交互时,就会出现竞争条件。例如,如果一个线程设置了一个全局变量,然后第二个线程读取并修改了该全局变量,而第一个线程读取了该变量,则第一个线程可能会遇到错误,因为该变量已意外更改。

    【讨论】:

      【解决方案3】:

      死锁:

      1. 2 个或更多 个线程等待彼此无限期地释放资源时,就会发生这种情况。
      2. 在此线程处于阻塞状态且未执行。

      比赛/比赛条件:

      1. 2 个或更多 线程并行运行 但最终给出的结果是错误的并且如果所有操作都不等效时,就会发生这种情况是按顺序完成的。
      2. 所有线程都在此处运行并执行操作。

      在编码中,我们需要避免竞争和死锁情况。

      【讨论】:

        【解决方案4】:

        我假设您的意思是“竞争条件”而不是“围绕条件竞争”(我听说过这个词......)

        基本上,死锁是线程A在等待资源X的同时持有资源Y的锁,而线程B在等待资源Y的同时持有资源X的锁。线程相互阻塞等待释放他们的锁。

        这个问题的解决方案是(通常)确保您在所有线程中以相同的顺序锁定所有资源。例如,如果你总是锁定资源 Xbefore 资源 Y,那么我的示例永远不会导致死锁。

        竞态条件是指您依赖以特定顺序发生的特定事件序列,但如果另一个线程同时运行,则可能会搞砸。例如,要在链表中插入一个新节点,就需要修改链表头,通常是这样的:

        newNode->next = listHead;
        listHead = newNode;
        

        但如果两个线程同时执行此操作,那么您可能会遇到这样运行的情况:

        Thread A                       Thread B
        newNode1->next = listHead
                                       newNode2->next = listHead
                                       listHead = newNode2
        listHead = newNode1
        

        如果发生这种情况,线程 B 对列表的修改将会丢失,因为线程 A 会覆盖它。情况可能更糟,具体取决于具体情况,但这是基本情况。

        这个问题的解决方案通常是确保你包含了正确的锁定机制(例如,在你想要修改链表的任何时候取出一个锁,这样一次只有一个线程在修改它)。

        【讨论】:

          【解决方案5】:

          如果你没有锁定共享资源并且被多个线程访问,那么它被称为“竞争条件”,第二种情况如果你锁定了资源并且对共享资源的访问顺序没有正确定义,那么线程可能需要很长时间才能等待资源使用然后这是“死锁”的情况

          【讨论】:

            猜你喜欢
            • 2015-01-16
            • 2012-10-27
            • 1970-01-01
            • 1970-01-01
            • 2010-11-06
            • 2014-11-08
            • 1970-01-01
            • 2012-04-17
            • 1970-01-01
            相关资源
            最近更新 更多