使用队列实现信号量

时间:2016-11-22 02:34:55

标签: java multithreading semaphore

我正在尝试使用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();
  }
}

1 个答案:

答案 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();
        }
    }
}