Подтвердить что ты не робот

Разница между условиями раскола и тупиковой ситуацией

В чем разница между мертвой блокировкой и расходом вокруг условия в терминах программирования?

4b9b3361

Ответ 1

Подумайте о состоянии гонки, используя традиционный пример. Скажем, у вас и у друга есть банкоматы для одного и того же банковского счета. Теперь предположим, что в учетной записи есть 100 долларов. Подумайте, что произойдет, когда вы попытаетесь снять 10 долларов, а ваш друг попытается снять 50 долларов в то же время.

Подумайте о том, что должно произойти. Банкомат должен взять ваш вход, прочитать то, что сейчас находится в вашей учетной записи, а затем изменить сумму. Обратите внимание, что в терминах программирования оператор присваивания представляет собой многоэтапный процесс.

Итак, назовите обе ваши транзакции 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", тогда эта проблема не возникнет. (Вы можете изменить предыдущий пример с учетом этого правила и не видеть, что тупик происходит).

Это тривиальные примеры, и на самом деле я только что использовал примеры, которые вы, возможно, уже видели, если вы приняли какой-либо курс обучения по этому курсу. На самом деле решение проблем с тупиками может быть намного сложнее, потому что вы, как правило, имеете более чем пару ресурсов и пару транзакций, взаимодействующих друг с другом.

Надеюсь, это поможет немного. Как всегда, используйте Википедию в качестве отправной точки для концепций CS:

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

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

Ответ 2

Тупик - это когда два (или более) потока блокируют друг друга. Обычно это как-то связано с потоками, пытающимися получить общие ресурсы. Например, если потоки T1 и T2 должны приобретать оба ресурса A и B для выполнения своей работы. Если T1 приобретает ресурс A, тогда T2 приобретает ресурс B, тогда T1 может ожидать ресурс B, в то время как T2 ожидает ресурс A. В этом случае оба потока будут бесконечно ждать ресурса, принадлежащего другому потоку. Эти потоки, как говорят, зашли в тупик.

Условия гонки происходят, когда два потока взаимодействуют с отрицательным (багги) способом в зависимости от точного порядка выполнения их различных инструкций. Например, если один поток задает глобальную переменную, то второй поток считывает и изменяет эту глобальную переменную, а первый поток читает переменную, первый поток может испытывать ошибку, поскольку переменная неожиданно изменилась.

Ответ 3

Я предполагаю, что вы имеете в виду "условия гонки", а не "расы вокруг условий" (я слышал этот термин...)

В принципе, мертвая блокировка - это условие, когда поток A ожидает ресурса X, удерживая блокировку на ресурсе Y, а поток B ждет ресурса Y, удерживая блокировку на ресурсе X. Блок потоков, ожидающий друг друга чтобы освободить их блокировки.

Решение этой проблемы (обычно), чтобы обеспечить блокировку всех ресурсов в одном порядке во всех потоках. Например, если вы всегда блокируете ресурс X до ресурса Y, то мой пример никогда не может привести к тупиковой ситуации.

Состояние гонки - это то, где вы полагаетесь на определенную последовательность событий, происходящих в определенном порядке, но это может быть испорчено, если другой поток работает одновременно. Например, чтобы вставить новый node в связанный список, вам нужно изменить заголовок списка, как правило, примерно так:

newNode->next = listHead;
listHead = newNode;

Но если два потока выполняются в одно и то же время, тогда у вас может быть ситуация, когда они работают так:

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

Если бы это произошло, то модификация списка Thread B будет потеряна, потому что Thread A переписал бы ее. Это может быть еще хуже, в зависимости от конкретной ситуации, но что основы этого.

Решение этой проблемы обычно заключается в том, что вы включаете правильные механизмы блокировки (например, вынимаете блокировку в любое время, когда хотите изменить связанный список, чтобы только один поток изменял ее за раз).