Нет тупика - но почему?Четыре условия - PullRequest
0 голосов
/ 21 ноября 2018

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

Редактировать: Поскольку люди неоднократно спрашивали меня, в чем проблема с моим кодом, потому что тупик не может возникнуть, я хочу сказать, что ничего нетчто-то не так, я просто хочу знать, ПОЧЕМУ это не может произойти.Есть четыре условия, которые должны быть выполнены для возникновения тупика, который можно найти здесь https://en.wikipedia.org/wiki/Deadlock#Necessary_conditions.Я явно предотвратил хотя бы одно условие, иначе мой код мог бы привести к тупику.Теперь я просто хочу узнать КАКОЕ условий, которые я предотвращал.

Мой код буфера выглядит так:

private String[] store;
private int capacity;

private int nextIn;
private int nextOut;

private Semaphore mutex = new Semaphore(1);
private Semaphore numAvail = new Semaphore(0); //available items to consume
private Semaphore numFree; //free slots in buffer

public Buffer(int capacity) {
    this.capacity = capacity;
    this.store = new String[capacity];
    numFree = new Semaphore(capacity);
}

public void insert(String item) {

    try {
        //acquire a free slot in the array
        numFree.acquire();

        //get permit to insert
        mutex.acquire();
    } catch (InterruptedException ex) {
        Thread.currentThread().interrupt();
    }

    //critical region - insert to body
    store[nextIn] = item;

    nextIn++;

    //when at end of array begin at index 0 again
    if (nextIn == capacity) {
        nextIn = 0;
    }

    //signal that there is an item available
    numAvail.release();

    //signal that another thread can consume or produce now
    mutex.release();
}

public String take() {
    String item;

    try {
        //check if item exists to consume
        numAvail.acquire();

        //get permit to take
        mutex.acquire();

    } catch (InterruptedException ex) {
        Thread.currentThread().interrupt();
        ex.printStackTrace();
    }

    //critical region
    item = store[nextOut];

    nextOut++;

    if (nextOut == capacity) {
        nextOut = 0;
    }


    //signal other threads that they can consume or produce
    mutex.release();

    //signal that there is a free slot to insert now
    numFree.release();

    return item;
}

1 Ответ

0 голосов
/ 21 ноября 2018

Я полагаю, что вы предотвратили циклическое ожидание.

Круговое ожидание происходит, когда каждый процесс ожидает ресурс, который удерживается другим процессом .

В вашем примереединственный ресурс, который ожидает, пока удерживается другой ресурс, - это мьютекс.Тем не менее, поток, содержащий мьютекс, никогда ничего не ждет.

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

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