Я пытаюсь создать базовую реализацию Semaphore с использованием Queue. Идея в том, что есть база данных, и есть 10 авторов. Писатели могут писать только в базу данных во взаимном исключении. Я использую Queue, потому что хочу реализовать First In First Out и Last In First Out.Реализация семафора с очередью
Используя Семафор, я не могу уведомить конкретный поток, чтобы проснуться. Поэтому моя идея заключается в том, что я делаю для каждого Writer, я создаю объект и говорю Writer ждать этого объекта. Помещает этот объект в очередь. Затем удалите объект из очереди и сообщите об этом Thread, ожидающем этого объекта. Таким образом, я думаю, что могу сделать реализацию FIFO или LIFO.
Мне нужна помощь по реализации фактического кода: 1. Я запускаю код ниже, он дал мне много IllegalMonitorStateException. 2. Код FIFO и LIFO (мой код FIFO кажется неправильным, а для кода LIFO я думаю использовать Stack вместо Queue).
public class Test {
public static void main(String [] args) {
Database db = new Database();
for (int i = 0; i < 10; i++)
(new Thread(new Writer(db))).start();
}
}
public class Writer implements Runnable {
private Database database;
public Writer(Database database) {
this.database = database;
}
public void run() {
this.database.acquireWriteLock();
this.database.write();
this.database.releaseWriteLock();
}
}
public class Database {
private Semaphore lockQueue;
public Database() {
this.lockQueue = new Semaphore();
}
public void write() {
try {
Thread.sleep(1000);
} catch (InterruptedException ie) {}
}
public void acquireWriteLock() {
lockQueue.acquire();
}
public void releaseWriteLock() {
lockQueue.release();
}
}
import java.util.Queue;
import java.util.LinkedList;
public class Semaphore {
private Queue<Object> queue;
public Semaphore() {
this.queue = new LinkedList<Object>();
}
public synchronized void acquire() {
Object object = new Object();
try {
if (this.queue.size() > 0) {
object.wait();
this.queue.add(object);
}
} catch (InterruptedException ie) {}
this.queue.add(object);
}
public synchronized void release() {
Object object = this.queue.remove();
object.notify();
}
}
В чем разница между этим кодом и тот, который я написал выше? Я использую 'object.wait()' вместо 'wait()', потому что я хочу ждать этого объекта, поэтому я могу использовать его как очередь. Если я просто использую 'wait()', не означает ли это, что я жду этого экземпляра Semaphore, и когда я делаю 'notify()', я не могу сообщить об определенном потоке, чтобы проснуться. –
Я редактировал код основанный на следующих причинах: 1st, IllegalMonitorStateException выбрасывается, поскольку экземпляр Semaphore заблокирован вместо экземпляра объекта. 2, вместо размера очереди используется целое число, определяющее, есть ли рабочие потоки. Если размер Queue используется, и объект добавлен, поток может удалить один и тот же объект, что приведет к взаимоблокировке. –
Спасибо, это именно то, что мне нужно. Можете ли вы подробнее рассказать о том, почему это синхронизированный блок при приобретении и выпуске вместо синхронизированных методов. –