Какая разница между тупиком и ливнем?

Может кто-нибудь объяснить примеры (кода), в чем разница между тупиком и livelock?

Ответ 1

Взято из http://en.wikipedia.org/wiki/Deadlock:

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

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

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

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

Ответ 2

Livelock

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

Как и в случае тупика, потоки, оставшиеся в живых, неспособны сделать дальнейший прогресс. Тем не менее, потоки не заблокированы - они просто слишком заняты, реагируя друг на друга, чтобы возобновить работу. Это сопоставимо с двумя людьми, пытающимися пройти друг в друга в коридоре: Альфонс движется влево, чтобы пройти Гастон, а Гастон направляется вправо, чтобы пройти Альфонса. Увидев, что они все еще блокируют друг друга, Альфонс движется направо, а Гастон движется влево. Они все еще блокируют друг друга и так далее...

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

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

enter image description here

Ответ 3

Все содержание и примеры из

Операционные системы: внутренние принципы и принципы проектирования
Уильям Столлингс
Выпуск 8º

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

Например, рассмотрим два процесса: P1 и P2 и два ресурса R1 и R2. Предположим, что каждый процесс нуждается в доступе к обоим ресурсам для выполнения части своей функции. Тогда возможно иметь следующую ситуацию: ОС назначает R1 в P2, а R2 - P1. Каждый процесс ждет одного из двух ресурсов. Также не будет выпущен ресурс, который он уже владеет, пока не приобретет другого ресурса и выполнил функцию, требующую обоих ресурсов. Два процессы зашли в тупик

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

Голодание. Ситуация, при которой выполняемый процесс игнорируется планировщиком неопределенно долго; хотя он может продолжать, он никогда не выбирается.

Предположим, что три процесса (P1, P2, P3) требуют периодического доступа к ресурсу R. Рассмотрим ситуацию, в которой P1 находится во владении ресурсом, и оба P2 и P3 задерживаются, ожидая этого ресурса. Когда P1 выходит из своего критического раздела, P2 или P3 должны иметь доступ к R. Предположим, что ОС предоставляет доступ к P3 и что P1 снова требует доступа, прежде чем P3 завершит свою критическую секцию. Если ОС предоставляет доступ к P1 после завершения P3 и впоследствии поочередно предоставляет доступ к P1 и P3, тогда P2 может неограниченно лишать доступа к ресурсу, даже несмотря на отсутствие ситуации взаимоблокировки.

ПРИЛОЖЕНИЕ A - ТЕМЫ В CONCURRENCY

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

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

/* PROCESS 0 */
flag[0] = true; 
while (flag[1]) 
    /* do nothing */; 
/* critical section*/; 
flag[0] = false; 

 /* PROCESS 1 */
flag[1] = true;
while (flag[0])
    /* do nothing */;
/* critical section*/;
flag[1] = false;

Пример Livelock

/* PROCESS 0 */
flag[0] = true; 
while (flag[1]){
    flag[0] = false; 
    /*delay */;
    flag[0] = true;
}
/*critical section*/;
flag[0] = false; 

/* PROCESS 1 */
flag[1] = true;
while (flag[0]) {
    flag[1] = false;
    /*delay */;
    flag[1] = true;
}
/* critical section*/;
flag[1] = false;

[...] рассмотрим следующую последовательность событий:

  • P0 устанавливает флаг [0] в true.
  • P1 устанавливает флаг [1] в true.
  • P0 проверяет флаг [1].
  • P1 проверяет флаг [0].
  • P0 устанавливает флаг [0] в false.
  • P1 устанавливает флаг [1] в false.
  • P0 устанавливает флаг [0] в true.
  • P1 устанавливает флаг [1] в true.

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

Ответ 4

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

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

Ответ 5

Возможно, эти два примера иллюстрируют вам разницу между тупиком и ливнем:


Java-пример для тупика:

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class DeadlockSample {

    private static final Lock lock1 = new ReentrantLock(true);
    private static final Lock lock2 = new ReentrantLock(true);

    public static void main(String[] args) {
        Thread threadA = new Thread(DeadlockSample::doA,"Thread A");
        Thread threadB = new Thread(DeadlockSample::doB,"Thread B");
        threadA.start();
        threadB.start();
    }

    public static void doA() {
        System.out.println(Thread.currentThread().getName() + " : waits for lock 1");
        lock1.lock();
        System.out.println(Thread.currentThread().getName() + " : holds lock 1");

        try {
            System.out.println(Thread.currentThread().getName() + " : waits for lock 2");
            lock2.lock();
            System.out.println(Thread.currentThread().getName() + " : holds lock 2");

            try {
                System.out.println(Thread.currentThread().getName() + " : critical section of doA()");
            } finally {
                lock2.unlock();
                System.out.println(Thread.currentThread().getName() + " : does not hold lock 2 any longer");
            }
        } finally {
            lock1.unlock();
            System.out.println(Thread.currentThread().getName() + " : does not hold lock 1 any longer");
        }
    }

    public static void doB() {
        System.out.println(Thread.currentThread().getName() + " : waits for lock 2");
        lock2.lock();
        System.out.println(Thread.currentThread().getName() + " : holds lock 2");

        try {
            System.out.println(Thread.currentThread().getName() + " : waits for lock 1");
            lock1.lock();
            System.out.println(Thread.currentThread().getName() + " : holds lock 1");

            try {
                System.out.println(Thread.currentThread().getName() + " : critical section of doB()");
            } finally {
                lock1.unlock();
                System.out.println(Thread.currentThread().getName() + " : does not hold lock 1 any longer");
            }
        } finally {
            lock2.unlock();
            System.out.println(Thread.currentThread().getName() + " : does not hold lock 2 any longer");
        }
    }
}

Пример вывода:

Thread A : waits for lock 1
Thread B : waits for lock 2
Thread A : holds lock 1
Thread B : holds lock 2
Thread B : waits for lock 1
Thread A : waits for lock 2

Java-пример для livelock:

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class LivelockSample {

    private static final Lock lock1 = new ReentrantLock(true);
    private static final Lock lock2 = new ReentrantLock(true);

    public static void main(String[] args) {
        Thread threadA = new Thread(LivelockSample::doA, "Thread A");
        Thread threadB = new Thread(LivelockSample::doB, "Thread B");
        threadA.start();
        threadB.start();
    }

    public static void doA() {
        try {
            while (!lock1.tryLock()) {
                System.out.println(Thread.currentThread().getName() + " : waits for lock 1");
                Thread.sleep(100);
            }
            System.out.println(Thread.currentThread().getName() + " : holds lock 1");

            try {
                while (!lock2.tryLock()) {
                    System.out.println(Thread.currentThread().getName() + " : waits for lock 2");
                    Thread.sleep(100);
                }
                System.out.println(Thread.currentThread().getName() + " : holds lock 2");

                try {
                    System.out.println(Thread.currentThread().getName() + " : critical section of doA()");
                } finally {
                    lock2.unlock();
                    System.out.println(Thread.currentThread().getName() + " : does not hold lock 2 any longer");
                }
            } finally {
                lock1.unlock();
                System.out.println(Thread.currentThread().getName() + " : does not hold lock 1 any longer");
            }
        } catch (InterruptedException e) {
            // can be ignored here for this sample
        }
    }

    public static void doB() {
        try {
            while (!lock2.tryLock()) {
                System.out.println(Thread.currentThread().getName() + " : waits for lock 2");
                Thread.sleep(100);
            }
            System.out.println(Thread.currentThread().getName() + " : holds lock 2");

            try {
                while (!lock1.tryLock()) {
                    System.out.println(Thread.currentThread().getName() + " : waits for lock 1");
                    Thread.sleep(100);
                }
                System.out.println(Thread.currentThread().getName() + " : holds lock 1");

                try {
                    System.out.println(Thread.currentThread().getName() + " : critical section of doB()");
                } finally {
                    lock1.unlock();
                    System.out.println(Thread.currentThread().getName() + " : does not hold lock 1 any longer");
                }
            } finally {
                lock2.unlock();
                System.out.println(Thread.currentThread().getName() + " : does not hold lock 2 any longer");
            }
        } catch (InterruptedException e) {
            // can be ignored here for this sample
        }
    }
}

Пример вывода:

Thread B : holds lock 2
Thread A : holds lock 1
Thread A : waits for lock 2
Thread B : waits for lock 1
Thread B : waits for lock 1
Thread A : waits for lock 2
Thread A : waits for lock 2
Thread B : waits for lock 1
Thread B : waits for lock 1
Thread A : waits for lock 2
Thread A : waits for lock 2
Thread B : waits for lock 1
...

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

Ответ 6

С ссылкой: http://operatingsystemgeeks.blogspot.in/ Пример тупика: Условие взаимного исключения применяется, поскольку только одно транспортное средство может находиться на участке улицы за раз. Состояние ожидания и ожидания действует, так как каждый автомобиль занимает участок улицы и ждет перехода к следующему разделу улицы. Неприемлемое условие применяется, поскольку участок улицы, являющийся участком улицы, которая занята транспортным средством, не может быть отнята у него. Условие циклического ожидания действует, так как каждое транспортное средство ждет на следующем транспортном средстве для перемещения. То есть каждое транспортное средство в трафике ждет участок улицы, удерживаемый следующим транспортным средством в трафике.