У меня проблема с продюсером-потребителем, и я решил ее с помощью семафоров, но не могу формально объяснить, какое из четырех условий, необходимых для тупика, я предотвратил.Это не может быть взаимоисключающий доступ или исключение, которое оставляет либо циклическое ожидание, либо удержание и ожидание.Я явно пытаюсь получить два ресурса как в методах вставки, так и в методах взятия, которые намекают на удержание и ожидание существования.Теперь осталось только круговое ожидание, которое я должен был предотвратить, но как?Или мои рассуждения неверны, и это не круговое ожидание?
Редактировать: Поскольку люди неоднократно спрашивали меня, в чем проблема с моим кодом, потому что тупик не может возникнуть, я хочу сказать, что ничего нетчто-то не так, я просто хочу знать, ПОЧЕМУ это не может произойти.Есть четыре условия, которые должны быть выполнены для возникновения тупика, который можно найти здесь 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;
}