我正在尝试使用Queue创建一个基本的Semaphore实现。这个想法是,有一个数据库,有10个作家。作者只能互斥地写入数据库。我正在使用Queue,因为我想实现先进先出和后进先出。
使用信号量,我无法通知特定线程唤醒。所以我的想法是我正在做的是为每个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();
}
}
答案 0 :(得分:1)
您需要获取对象的锁定才能使用wait()和notify()。 尝试检查以下代码是否有效:
public class Semaphore {
private Queue<Object> queue;
private int state;
public Semaphore() {
this.queue = new LinkedList<Object>();
}
public void acquire() {
Object object = new Object();
synchronized (object) {
try {
if (this.state > 0) {
this.queue.add(object);
object.wait();
} else {
state++;
}
} catch (InterruptedException ie) {
}
}
}
public void release() {
Object object = this.queue.poll();
state--;
if(null == object) {
return;
}
synchronized (object) {
object.notify();
}
}
}