Разница между условиями обхода и тупиком - PullRequest
45 голосов
/ 28 июня 2010

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

Ответы [ 4 ]

60 голосов
/ 28 июня 2010

Подумайте о состоянии гонки, используя традиционный пример.Допустим, у вас и вашего друга есть банкоматные карточки на один и тот же банковский счет.Теперь предположим, что на счете 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

12 голосов
/ 28 июня 2010

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

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

5 голосов
/ 25 июля 2018

тупик:

  1. Это происходит, когда 2 или более потоков ожидают друг на другаосвободить ресурс на бесконечное количество времени.
  2. При этом потоки находятся в заблокированном состоянии и не выполняются.

Race / Race Условие:

  1. Это происходит, когда 2 или более потоков работают параллельно , но в итоге дают результат, который является неправильным и не эквивалентным, если всеОперации выполняются в последовательном порядке.
  2. Здесь все потоки запускаются и выполняют там свои операции.

В кодировании нам нужно избегать как состояния гонки, так и состояния тупика.

5 голосов
/ 28 июня 2010

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

По сути, мертвая блокировка - это состояние, при котором поток A ожидает ресурс X, удерживая блокировку ресурса Y, а поток B ожидает ресурс Y, удерживая блокировку ресурса X. Блоки потоков ожидают друг друга. освободить свои замки.

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

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

newNode->next = listHead;
listHead = newNode;

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

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

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

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

...