Может кто-нибудь объяснить с примерами (кода), в чем разница между взаимоблокировками и livelock ?
multithreading
pthreads
deadlock
livelock
macindows
источник
источник
Ответы:
Взято с http://en.wikipedia.org/wiki/Deadlock :
источник
динамический тупик
Основное различие между livelock и deadlock состоит в том, что потоки не будут блокироваться, вместо этого они будут пытаться отвечать друг другу непрерывно.
На этом изображении оба круга (нити или процессы) будут пытаться освободить место для другого, перемещаясь влево и вправо. Но они не могут двигаться дальше.
источник
Все содержание и примеры здесь взяты из
Операционные системы: внутреннее устройство и принципы проектирования
William Stallings
8º Edition
Тупик : ситуация, в которой два или более процесса не могут продолжаться, потому что каждый ждет, что другие что-то предпримут.
Например, рассмотрим два процесса, P1 и P2, и два ресурса, R1 и R2. Предположим, что каждому процессу необходим доступ к обоим ресурсам для выполнения части его функций. Тогда возможна следующая ситуация: ОС назначает R1 для P2 и R2 для P1. Каждый процесс ожидает один из двух ресурсов. Ни один из них не освободит ресурс, которым он уже владеет, до тех пор, пока он не получит другой ресурс и не выполнит функцию, требующую обоих ресурсов. Два процесса заблокированы
Живая блокировка : ситуация, в которой два или более процессов непрерывно изменяют свои состояния в ответ на изменения в других процессах без какой-либо полезной работы:
Голодание : Ситуация, когда планировщик игнорирует запущенный процесс на неопределенный срок; хотя он может продолжать, он никогда не выбирается.
Предположим, что каждому из трех процессов (P1, P2, P3) требуется периодический доступ к ресурсу R. Рассмотрим ситуацию, когда P1 владеет ресурсом, и P2 и P3 задерживаются, ожидая этого ресурса. Когда P1 выходит из своей критической секции, P2 или P3 должен быть разрешен доступ к R. Предположим, что ОС предоставляет доступ к P3 и что P1 снова требует доступ до того, как P3 завершит свою критическую секцию. Если ОС предоставляет доступ к P1 после завершения P3 и впоследствии поочередно предоставляет доступ к P1 и P3, то P2 может быть неограниченно запрещен доступ к ресурсу, даже если нет ситуации взаимоблокировки.
ПРИЛОЖЕНИЕ А - ТЕМЫ В ВАЛЮТЕ
Пример тупика
Если оба процесса устанавливают свои флаги в true до того, как один из них выполнит оператор while, то каждый из них будет думать, что другой вошел в критическую секцию, вызывая взаимоблокировку.
Пример живой блокировки
[...] рассмотрим следующую последовательность событий:
Эта последовательность может быть расширена до бесконечности, и ни один из процессов не сможет войти в ее критическую секцию. Строго говоря, это не тупик , потому что любое изменение относительной скорости двух процессов нарушит этот цикл и позволит войти в критическую секцию. Это условие называется livelock . Напомним, что тупик возникает, когда набор процессов хочет войти в свои критические секции, но ни один процесс не может быть успешным. При использовании livelock возможны последовательности успешных исполнений, но также возможно описать одну или несколько последовательностей выполнения, в которых ни один процесс не входит в свою критическую секцию.
Не содержание из книги больше.
А как насчет спинлок?
Spinlock - это метод, позволяющий избежать затрат на механизм блокировки ОС. Обычно вы делаете:
Проблема начинает появляться, когда
beginLock()
стоит намного больше, чемdoSomething()
. В очень преувеличенном виде представьте, что происходит, когдаbeginLock
стоит 1 секунда, аdoSomething
стоит всего 1 миллисекунда.В этом случае, если вы подождали 1 миллисекунду, вам бы не мешали в течение 1 секунды.
Почему это
beginLock
будет стоить так дорого? Если блокировка свободна, это не стоит больших затрат (см. Https://stackoverflow.com/a/49712993/5397116 ), но если блокировка не свободна, ОС «заморозит» ваш поток, настройте механизм, чтобы разбудить вас когда замок будет освобожден, а затем снова разбудить вас в будущем.Все это намного дороже, чем некоторые петли, проверяющие блокировку. Вот почему иногда лучше сделать «спинлок».
Например:
Если ваша реализация не является осторожной, вы можете упасть на livelock, потратив все ресурсы процессора на механизм блокировки.
Также см:
https://preshing.com/20120226/roll-your-own-lightweight-mutex/
Является ли моя реализация спин-блокировки правильной и оптимальной?
Резюме :
Тупик : ситуация, когда никто не прогрессирует, ничего не делает (спит, ждет и т. Д.). Загрузка процессора будет низкой;
Livelock : ситуация, когда никто не прогрессирует, но процессор расходуется на механизм блокировки, а не на ваш расчет;
Голодание: ситуация, когда один прогресс никогда не получает шанс бежать; по чистой случайности или по какой-либо причине (например, с низким приоритетом);
Спинлок : метод избежания затрат, ожидающих освобождения блокировки.
источник
DEADLOCK Deadlock - это состояние, при котором задача ожидает в течение неопределенного времени условий, которые никогда не могут быть выполнены - задача требует исключительного контроля над общими ресурсами - задача удерживает ресурсы при ожидании освобождения других ресурсов - задачи нельзя принудительно перераспределить ресурсы - циклическое ожидание условие существует
LIVELOCK Условия Livelock могут возникать, когда две или более задач зависят от некоторого ресурса и используют его, вызывая состояние циклической зависимости, при котором эти задачи продолжают выполняться вечно, таким образом блокируя выполнение всех задач с более низким приоритетом (эти задачи с более низким приоритетом испытывают состояние, называемое голоданием)
источник
Возможно, эти два примера иллюстрируют разницу между тупиком и livelock:
Java-пример для тупика:
Образец вывода:
Java-пример для livelock:
Образец вывода:
Оба примера заставляют нити приобретать замки в разных порядках. В то время как тупик ожидает другую блокировку, livelock на самом деле не ждет - он отчаянно пытается захватить блокировку без возможности ее получить. Каждая попытка потребляет циклы процессора.
источник
Представьте, что у вас поток A и поток B. Они оба находятся
synchronised
в одном объекте, и внутри этого блока есть глобальная переменная, которую они оба обновляют;Таким образом, когда поток А входит в
while
петлю и удерживает блокировку, он делает то , что он должен делать , и установитьcommonVar
вtrue
. Затем нить B входит, входит вwhile
петлю и , так какcommonVar
этоtrue
сейчас, это быть в состоянии удерживать замок. Это делает, выполняетsynchronised
блок и устанавливаетcommonVar
обратноfalse
. Теперь поток А снова получает это новое окно CPU, он был собирается выйти изwhile
цикла , но поток B только установить его обратноfalse
, так что цикл повторяется снова. Потоки что-то делают (поэтому они не блокируются в традиционном смысле), но практически ничего.Также может быть приятно упомянуть, что здесь не обязательно должен появляться livelock. Я предполагаю, что планировщик предпочитает другой поток после
synchronised
завершения выполнения блока. Большую часть времени я думаю, что это сложное ожидание и зависит от многих вещей, происходящих под капотом.источник