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

Как объяснить "тупик" лучше?

Я изо всех сил пытаюсь объяснить "тупик" в потоках, поэтому, пожалуйста, помогите. Что может быть лучшим примером "тупика" (скажем, на Java) и как это происходит в шагах и как его предотвратить? Но не углубляясь в детали. Я знаю, что, как просить две противоположные вещи, но все же. Если у вас есть какой-либо предыдущий опыт совместной подготовки к программированию - это было бы превосходно!

4b9b3361

Ответ 1

Джек и Джилл, похоже, хотят сделать бутерброд одновременно. Оба нуждаются в куске хлеба, поэтому они оба идут, чтобы получить буханку хлеба и нож.

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

Ответ 2

Самый простой способ - два разных потока попытаться получить две блокировки в разных порядках:

thread 1:
lock(a)
lock(b)

thread2:
lock(b)
lock(a)

Предположим, что поток 1 получает блокировку A и затем переходит в режим сна. Нить 2 получает блокировку B, а затем пытается получить блокировку A; так как блокировка A берется, поток 2 будет спать до тех пор, пока нить A не разблокируется. Теперь поток 1 просыпается и пытается получить блокировку B и будет усыпан.

В этом случае существует несколько способов предотвратить это:

  • Нить никогда не должна содержать две блокировки одновременно.
  • Если два замка должны удерживаться одновременно, их всегда нужно приобретать в том же порядке (поэтому в моем примере выше поток 2 необходимо будет изменить, чтобы запросить блокировку A перед запросом блокировки B).

Ответ 3

  Thrd 1 --- Lock A        - atmpt lock on B -   
         \                /                   \
          \              /                     \           
           \            /                       \         
            --- Lock A /                         --- wait for lock on B

  Thrd 2--- Lock B         - atmpt lock on A -   
         \                /                   \
          \              /                     \           
           \            /                       \         
            --- Lock B /                         --- wait for lock on A

Тема 1 работает, Locks A, делает некоторые вещи и прерывается Тема 2, которая блокирует B, делает некоторые вещи и прерывается Thread 1, который пытается заблокировать B, но нить 2 заблокировала B, поэтому поток 1 ждет и прерывается Thread 2, который пытается заблокировать A, но поток 1 имеет блокировку A, поэтому Thread 2 должен ждать.

Оба потока ждут, пока другой поток освободит блокировку ресурса, который они пытаются заблокировать...

взаимоблокировки

Ответ 4

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

У меня есть пятилетний сын и трехлетняя дочь. Оба хотят сделать одну и ту же раскраску.

Дочь захватывает карандаши, пока сын хватает книгу. Также они не откажутся от того, что у них есть, пока не получат другой.

Этот тупик. Это не упрощает.

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

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

Следующее одно правило гарантирует, что взаимоблокировка не может произойти:

  • Все потоки выполнения выделяют ресурсы в том же порядке.

Следуя некоторым дополнительным правилам, ваши потоки будут менее склонны замедлять друг друга, но имейте в виду, что вышеприведенное правило должно иметь приоритет над всеми остальными:

  • Выделите ресурсы только тогда, когда они вам понадобятся.
  • Отпустите их, как только вы закончите с ними.

Ответ 5

Еще один хороший способ продемонстрировать тупик - это SQL Server.

Используя транзакции с разными уровнями изоляции, вы можете продемонстрировать, как одна транзакция будет бесконечно ждать для таблицы, которая заблокирована другой транзакцией.

Плюс здесь, вы можете продемонстрировать его с помощью SQL Management Studio. Я использовал это в прошлом, чтобы объяснить взаимоблокировки для людей, изучая курсы обучения "Введение в SQL Server".

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

Вкратце: транзакция A (которая не завершена) принимает явную блокировку таблицы. Вторая транзакция B пытается прочитать из таблицы, заблокированной транзакцией A. Транзакция B зашла в тупик до тех пор, пока транзакция A не завершится или откатится.

Вы можете объяснить это в коде достаточно легко, создав два отдельных потока, которые, в свою очередь, создают транзакции. Надеюсь, что это поможет.

Ответ 6

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

Я изучил много концепций из параллельного программирования, используя эти примеры, реализованные на Java.

Ответ 7

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

Для взаимоблокировки требуется не менее 2 блокировок, и оба потока должны содержать код, который принимает блокировки, а также ожидает освобождения блокировок.

В потоке 1 есть блокировка A и требуется блокировка B, поэтому он ждет блокировки B, которая будет выпущена.

В потоке 2 есть блокировка B и требуется блокировка A, поэтому она ждет блокировки A, которая будет выпущена.

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

Ответ 8

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

В Википедии есть пара реальных реальных примеров тупика.

Ответ 9

Цепочка блокировки возникает, когда работник блокируется другим работником. A не может продолжаться из-за B. Цепочка может быть длиннее: A блокируется B, B блокируется C, C блокируется D.

Тупик - это когда цепь блокировки формирует цикл. A блокируется B, B на C, C на A, и цепь сформировала петлю, прогресс невозможен.

Типичным способом предотвращения взаимоблокировок является использование блокировок: если блокировки всегда используются каждым работником в одном порядке, то взаимоблокировки невозможны, поскольку каждая блокировка происходит между работником, чем содержит блокировки, ранжированные по X, и ожидает ранжирования ресурсов Y, где X > Y всегда. В этом случае цикл не может образовываться, поскольку для закрытия цикла требуется, по крайней мере, один рабочий, чтобы идти против иерархии. Это как теория, по крайней мере. В prcatice очень сложно найти реалистичные иерархии (и нет, адрес ресурса не работает).

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

Ответ 10

(Немного упрощенно) Есть два человека, завинчивающие гайки на болтах.

Процедура (такая же для обоих):

  • Поднимите гайку или болт.
  • Возьмите болт или гайку (в зависимости от того, что у вас еще нет)
  • Вверните гайку на болт
  • Поместите готовое собрание в кучу "Готово".
  • Если гайки и болты остаются, перейдите к шагу 1

Итак, что происходит, когда осталось только гайка и болт? Первый человек забирает орех, второй захватывает болт. Пока все хорошо, но теперь они застревают, у каждого есть ресурс, который нужен другим.

Без специальных инструкций они будут сидеть там в тупике навсегда.

Или вы можете просто показать им это видео

Ответ 11

Обеденные философы - у вас 4 человека, сидящих за столом, и 4 палочки для еды. Вам нужно 2 палочки для еды. Представьте, что каждый философ пытается поесть следующим образом:

  • Возьмите левую палочку для еды.
  • Поднимите правую палочку для еды.
  • Eat.
  • Установите правую палочку назад.
  • Установите левую палочку назад.

Каждый делает шаг 1. Теперь шаг 2 невозможен, так как каждый человек ждет того, кто по праву может отбросить левое, чего они не сделают. Это тупик. Если они просто по очереди, то все могут есть, но вместо этого все голодают.

Ответ 12

Описание Гуффа хорошее.

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

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

Эта статья хорошо читает об этой проблеме.

Ответ 14

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

Ответ 15

Представьте, что преступник держит заложника и просит выкупа. Вы показываетесь с чемоданом, полным денег.

Преступник никогда не освободит заложника до того, как получит деньги. Вы никогда не освободите деньги до того, как получите заложника. Тупик.


Аналогия здесь:

  • Вы и преступник - это threads
  • Чемодан с деньгами и заложником - это ресурсы