Вопрос

При написании многопоточных приложений одной из наиболее распространенных проблем являются взаимоблокировки.

Мои вопросы к сообществу следующие:

  1. Что такое тупиковая ситуация?

  2. Как вы их обнаруживаете?

  3. Вы справляетесь с ними?

  4. И, наконец, как вы предотвращаете их возникновение?

Это было полезно?

Решение

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

Один процесс проигрывает и должен ждать завершения другого.

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

Итак, пример:

Ресурсы A и B используются процессами X и Y

  • X начинает использовать A.
  • X и Y пытаются начать использовать B
  • Y "выигрывает" и получает B первым
  • теперь Y нужно использовать A
  • A заблокирован X, который ожидает Y

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

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

Другие советы

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

Криминал & amp; Сцена полицейского

enter описание изображения здесь

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

Еще одно объяснение высокого уровня тупика: разбитые сердца

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

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

Способами избежать возникновения взаимоблокировок являются:

  • избегайте наличия блокировок (если это возможно),
  • избегайте наличия более чем одной блокировки
  • всегда устанавливайте замки в одном и том же порядке.

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

Процесс : . Как мы знаем, процесс - это не что иное, как программа в исполнении.

Ресурс : . Для выполнения процесса программы требуются некоторые ресурсы. Категории ресурсов могут включать память, принтеры, процессоры, открытые файлы, ленточные накопители, компакт-диски и т. Д.

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

Условие или ситуация тупика

введите описание изображения здесь

На приведенной выше диаграмме есть два процесса P1 и p2 , а также два ресурса R1 и R2 . .

Ресурс R1 выделен для процесса P1 , а ресурс R2 выделен для процесса p2 . Для завершения процесса P1 необходим ресурс R2 , поэтому P1 запрос для R2 , но R2 уже выделен для P2 .

Точно так же процесс P2 для завершения своего выполнения требует R1 , но R1 уже выделен для P1 .

оба процесса не могут освободить свой ресурс до тех пор, пока они не завершат свое выполнение. Так что оба ждут других ресурсов и будут ждать вечно. Так что это условие ЗАДЕРЖКА .

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

<Ол>
  • Взаимное исключение . Каждый ресурс в настоящее время либо выделен ровно одному процессу, либо он доступен. (Два процесса не могут одновременно контролировать один и тот же ресурс или быть в их критическом раздел).
  • Удерживать и ждать - процессы, в настоящее время удерживающие ресурсы, могут запрашивать новые ресурсы.
  • Без выгрузки . Если процесс удерживает ресурс, он не может быть удален другим процессом или ядром.
  • Циклическое ожидание . Каждый процесс ожидает получения ресурса, который удерживается другим процессом.
  • и все эти условия выполняются на приведенной выше диаграмме.

    Тупик возникает, когда поток ожидает чего-то, что никогда не происходит.

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

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

    Thread 1               Thread 2
    
    Lock1->Lock();         Lock2->Lock();
    WaitForLock2();        WaitForLock1();   <-- Oops!
    

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

    Вы можете взглянуть на эти замечательные статьи в разделе Deadlock . Это в C #, но идея остается той же для другой платформы. Я цитирую здесь для легкого чтения

      

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

    object locker1 = new object();
    object locker2 = new object();
    
    new Thread (() => {
                        lock (locker1)
                        {
                          Thread.Sleep (1000);
                          lock (locker2);      // Deadlock
                        }
                      }).Start();
    lock (locker2)
    {
      Thread.Sleep (1000);
      lock (locker1);                          // Deadlock
    }
    

    Взаимная блокировка является распространенной проблемой в многопроцессорных / многопрограммных задачах в ОС. Скажем, есть два процесса P1, P2 и два глобально разделяемых ресурса R1, R2, и в критическом разделе должны быть доступны оба ресурса

    Первоначально ОС назначает R1 для обработки P1 и R2 для обработки P2. Поскольку оба процесса работают одновременно, они могут начать выполнять свой код, но ПРОБЛЕМА возникает, когда процесс попадает в критическую секцию. Так что процесс R1 будет ждать, пока процесс P2 выпустит R2, и наоборот ... Так что они будут ждать вечно (СОСТОЯНИЕ ЗАГЛУШКИ).

    Небольшая АНАЛОГИЯ ...

      

    Твоя мама (О.С.),
      Вы (P1),
      Твой брат (P2),
      Яблоко (R1),
      Нож (R2)
      критическая секция (резка яблока ножом).      

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

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

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

    Тупик - это состояние системы, в котором ни один процесс / поток не может выполнить действие. Как упоминалось другими, взаимоблокировка обычно является результатом ситуации, когда каждый процесс / поток желает получить блокировку для ресурса, который уже заблокирован другим (или даже тем же) процессом / потоком.

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

    Некоторые более формальные методы могут быть полезны, если вы серьезно относитесь к решению подобных проблем. Наиболее практичный метод, который мне известен, - это использование теоретического подхода к процессу. Здесь вы моделируете свою систему на каком-либо языке процессов (например, CCS, CSP, ACP, mCRL2, LOTOS) и используете доступные инструменты для (моделирования) проверки на наличие взаимоблокировок (и, возможно, некоторых других свойств). Примерами используемых инструментов являются FDR, mCRL2, CADP и Uppaal. Некоторые смелые души могут даже доказать, что их системы зашли в тупик, используя чисто символические методы (доказательство теорем; ищите Овики-Гриза).

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

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

    Приведенные выше некоторые объяснения хороши.Надеюсь, это тоже может быть полезно:https://ora-data.blogspot.in/2017/04/deadlock-in-oracle.html

    В базе данных, когда сеанс (например,ora) хочет, чтобы ресурс принадлежал другому сеансу (например,данные), но этому сеансу (data) также нужен ресурс, который удерживается первым сеансом (ora).Также может быть задействовано более 2 сеансов, но идея будет той же.На самом деле взаимоблокировки препятствуют продолжению работы некоторых транзакций.Например:Предположим, ORA-DATA удерживает блокировку A и запрашивает блокировку B А SKU удерживает блокировку B и запрашивает блокировку A.

    Спасибо,

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

    Как избежать?
                     - Избегайте вложенных замков
     - Избегайте ненужных замков
     - Использовать нить join ()

    Как вы это обнаруживаете?
    запустите эту команду в cmd:

    jcmd $PID Thread.print
    

    ссылка : geeksforgeeks

    Классическая и очень простая программа для понимания ситуации тупика : -

    public class Lazy {
    
        private static boolean initialized = false;
    
        static {
            Thread t = new Thread(new Runnable() {
                public void run() {
                    initialized = true;
                }
            });
    
            t.start();
    
            try {
                t.join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    
        public static void main(String[] args) {
            System.out.println(initialized);
        }
    }
    

    Когда основной поток вызывает Lazy.main, он проверяет, является ли класс Lazy был инициализирован и начинает инициализировать класс. основной поток теперь устанавливает инициализированное значение false, создает и запускает фон поток, метод запуска которого устанавливает значение initialized в значение true и ожидает завершения фонового потока.

    На этот раз класс в настоящее время инициализируется другим потоком. В этих условиях текущий поток, который является фоновым потоком, ожидает объекта Class до завершения инициализации. К сожалению, поток который выполняет инициализацию, основной поток ожидает фон нить для завершения. Поскольку два потока теперь ждут друг друга, Программа ОТКЛЮЧЕНА.

    Проблема Тупиковой ситуации

    • Самые ранние компьютерные операционные системы запускали только одну программу одновременно
    • Все ресурсы системы были недоступны до этого программа
    • Позже операционные системы запускали несколько программ одновременно, чередуя их
    • От программ требовалось заранее указывать, какие ресурсы им необходимы, чтобы избежать конфликтов с другими программами, работающими одновременно
    • В конце концов, некоторые операционные системы предложили динамическое распределение ресурсов
    • Программы могли запрашивать дополнительное выделение ресурсов после того, как они начали работать
    • Это привело к проблеме тупиковой ситуации

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

    Ситуация, в которой 02 или более конкурирующих действий каждое ожидает завершения другого, и, таким образом, ни одно из них никогда не выполняется

    Характеристика тупиковой ситуации

    • Взаимное исключение
    • Держаться и ждать
    • Никакого Вытеснения
    • Круговое Ожидание

    Методы обработки взаимоблокировок

    • Убедитесь, что система никогда не войдет в состояние взаимоблокировки
    • Разрешить системе перейти в состояние взаимоблокировки, а затем восстановить
    • Игнорировать проблему и делать вид, что тупиковых ситуаций не возникает в системе;используется большинством операционных систем, включая UNIX

    Предотвращение взаимоблокировки

    • Взаимное исключение – не требуется для общих ресурсов;должен храниться для неразделяемых ресурсов

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

    • Никакого Вытеснения – Если процесс, который удерживает некоторые ресурсы, запрашивает другой ресурс, который не может быть выделен ему немедленно, то все ресурсы, которые в данный момент удерживаются, освобождаются

    • Круговое Ожидание – Установить общий порядок для всех типов ресурсов и потребовать, чтобы каждый процесс запрашивал ресурсы в порядке возрастания перечисления

    Мьютекс по сути - это блокировка, обеспечивающая защищенный доступ к общим ресурсам.В Linux типом данных мьютекса потока является pthread_mutex_t .Перед использованием инициализируйте его.

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

    В целом, существует несколько неписаных основных принципов:

    • Получите блокировку перед использованием общих ресурсов.

    • Удерживайте фиксатор как можно дольше.

    • Снимите блокировку, если поток возвращает ошибку.

    Лицензировано под: CC-BY-SA с атрибуция
    Не связан с StackOverflow
    scroll top