Взаимное исключение - Mutual exclusion

Два узла, и , удаление одновременно приводит к узлу не удаляется.

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

Требование взаимного исключения было впервые выявлено и решено Эдсгер В. Дейкстра в своей основополагающей статье 1965 года «Решение проблемы управления параллельным программированием»,[1][2] который считается первой темой в изучении параллельные алгоритмы.[3]

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

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

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

Описание проблемы

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

Успешное решение этой проблемы должно иметь как минимум эти два свойства:

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

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

  • Блокировка-свобода гарантирует, что любой процесс, желающий войти в критическую секцию, в конечном итоге сможет это сделать. Это отличается от предотвращения тупика, которое требует, чтобы немного ожидающий процесс может получить доступ к критической секции, но не требует, чтобы каждый процесс получил свою очередь. Если два процесса постоянно обмениваются ресурсами между собой, третий процесс может быть заблокирован и испытать ресурсный голод, даже если система не в тупике. Если в системе нет локаутов, это гарантирует, что каждый процесс в какой-то момент в будущем может быть изменен.
  • А k-ограниченное свойство ожидания дает более точное обязательство, чем свобода от локаута. Свобода блокировки гарантирует, что каждый процесс в конечном итоге сможет получить доступ к критической секции: она не дает никаких гарантий относительно того, как долго будет ждать. На практике процесс может быть обгонен произвольным или неограниченным числом раз другими процессами с более высоким приоритетом, прежде чем он дойдет до своей очереди. Под k-ограниченное время ожидания, каждый процесс имеет конечное максимальное время ожидания. Это работает, устанавливая ограничение на количество раз, когда другие процессы могут врезаться в линию, так что ни один процесс не может войти в критическую секцию больше, чем k раз, пока другой ждет.[4]

Программа каждого процесса может быть разбита на четыре части, что дает четыре состояния. Выполнение программы проходит через эти четыре состояния по порядку:[5]

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

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

Обеспечение взаимного исключения

Аппаратные решения

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

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

Некоторые другие атомарные операции могут использоваться для обеспечения взаимного исключения структур данных; наиболее заметным из них является сравнивать и менять местами (CAS). CAS можно использовать для достижения без ожидания взаимное исключение для любой совместно используемой структуры данных путем создания связанный список где каждый узел представляет желаемую операцию, которую нужно выполнить. Затем CAS используется для изменения указатели в связанном списке[6] во время вставки нового узла. Только один процесс может быть успешным в его CAS; всем остальным процессам, пытающимся одновременно добавить узел, придется повторить попытку. Затем каждый процесс может сохранить локальную копию структуры данных и при обходе связанного списка может выполнять каждую операцию из списка в своей локальной копии.

Программные решения

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

Эти алгоритмы не работают, если внеочередное исполнение используется на платформе, которая их выполняет. Программисты должны указать строгий порядок операций с памятью в потоке.[8]

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

Связанный проблемой взаимного исключения

Один двоичный файл проверить и установить register достаточно, чтобы обеспечить безупречное решение проблемы взаимного исключения. Но решение, построенное с использованием регистра тестирования и установки, может привести к остановке некоторых процессов, которые попадут в раздел попыток.[4] Фактически, различные состояния памяти необходимы, чтобы избежать блокировки. Чтобы избежать безграничного ожидания, п требуются различные состояния памяти.[9]

Восстанавливаемое взаимное исключение

Большинство алгоритмов взаимного исключения разработаны с предположением, что сбой не происходит, пока процесс выполняется внутри критической секции. Однако в действительности такие сбои могут быть обычным явлением. Например, внезапное отключение питания или неисправное межсоединение может привести к тому, что процесс в критическом разделе испытает неустранимую ошибку или не сможет продолжить работу по иным причинам. Если происходит такой сбой, обычные, отказоустойчивые алгоритмы взаимного исключения могут блокировать или иным образом приводить к отказу ключевых свойств жизнеспособности. Для решения этой проблемы было предложено несколько решений, использующих механизмы восстановления после сбоя.[10]

Типы устройств взаимного исключения

Решения, описанные выше, можно использовать для создания примитивов синхронизации ниже:

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

Многие исследования направлены на устранение вышеуказанных эффектов, часто с целью гарантировать неблокирующий прогресс. Совершенной схемы не известно. Блокировка системных вызовов, используемых для засыпания всего процесса. Пока такие звонки не стали потокобезопасный, не было надлежащего механизма для ожидания одного потока в процессе (см. опрос ).[нужна цитата ]

Смотрите также

Рекомендации

  1. ^ Дейкстра, Э. В. (1965). «Решение проблемы управления параллельным программированием». Коммуникации ACM. 8 (9): 569. Дои:10.1145/365559.365617. S2CID  19357737.
  2. ^ а б Таубенфельд, «Алгоритм Черно-Белой Пекарни». В Proc. Распределенные вычисления, 18-я международная конференция, DISC 2004. Том 18, 56-70, 2004
  3. ^ «Премия PODC Influential Paper Award: 2002», Симпозиум ACM по принципам распределенных вычислений, получено 24 августа 2009
  4. ^ а б Аттия, Хагит; Уэлч, Дженнифер (25 марта 2004 г.). Распределенные вычисления: основы, моделирование и дополнительные темы. John Wiley & Sons, Inc. ISBN  978-0-471-45324-6.
  5. ^ Лэмпорт, Лесли (26 июня 2000 г.), Проблема взаимного исключения, часть II: постановка и решения (PDF)
  6. ^ https://timharris.uk/papers/2001-disc.pdf
  7. ^ Лэмпорт, Лесли (август 1974). «Новое решение проблемы параллельного программирования Дейкстры». Коммуникации ACM. 17 (8): 453–455. Дои:10.1145/361082.361093. S2CID  8736023.
  8. ^ Хольцманн, Джерард Дж .; Боснацкий, Драган (1 октября 2007 г.). «Дизайн многоядерного расширения программы проверки модели SPIN» (PDF). IEEE Transactions по разработке программного обеспечения. 33 (10): 659–674. Дои:10.1109 / TSE.2007.70724. S2CID  9080331.
  9. ^ Бернс, Джеймс Э .; Пол Джексон, Нэнси А. Линч (январь 1982 г.), Требования к данным для реализации взаимного исключения N-процессов с использованием единой общей переменной (PDF)
  10. ^ Голаб, Войцех; Рамараджу, Адитья (июль 2016 г.), Исправимое взаимное исключение

дальнейшее чтение

  • Мишель Рейналь: Алгоритмы взаимного исключения, MIT Press, ISBN  0-262-18119-3
  • Сунил Р. Дас, Прадип К. Шримани: Распределенные алгоритмы взаимного исключения, Компьютерное общество IEEE, ISBN  0-8186-3380-8
  • Томас В. Кристофер, Джордж К. Тируватукал: Высокопроизводительные вычисления на платформе Java, Прентис Холл, ISBN  0-13-016164-0
  • Гади Таубенфельд, Алгоритмы синхронизации и параллельное программирование, Пирсон / Прентис Холл, ISBN  0-13-197259-6

внешняя ссылка