简体   繁体   English

我可以在 Java 中使用信号量实现阻塞队列吗?

[英]Can I implement blocking queue using Semaphore in Java?

I wonder if it is possible to use Semaphore to implement blocking queue?我想知道是否可以使用Semaphore来实现阻塞队列?

In the below codes, I use one Semaphore to protect the critical section, and two more Semaphore objects to track the number of empty slots and filled objects.在下面的代码中,我使用一个 Semaphore 来保护临界区,并使用另外两个 Semaphore 对象来跟踪空槽和填充对象的数量。

public class BlockingQueue {
  private List<Object> queue = new LinkedList<Object>();
  private int limit;
  private Semaphore slots; // semaphore for empty slots
  private Semaphore objs;  // semaphore for filled slots
  private Semaphore mutex; // for the critical section
  public BlockingQueue(int limit) {
    this.limit = limit;
    this.slots = new Semaphore(limit); // initial empty slot = capacity
    this.objs = new Semaphore(0);
    this.mutex = new Semaphore(1);
  }
  private void enqueue(Object o) throws InterruptedException {
    slots.acquire();
    mutex.acquire(); // critical section starts
    queue.add(o);
    mutex.release(); // critical section ends
    objs.release();
  }
  private Object dequeue() throws InterruptedException {
    objs.acquire();
    mutex.acquire(); // critical section starts
    Object o = queue.remove(0);
    mutex.release(); // critical section ends
    slots.release();
    return o;
  }
}

Adding to a previous comment - we can agree your code works (it's a well known algorithm), in particular you're correct in protecting the LinkedList since it's not internally thread safe.添加到先前的评论 - 我们可以同意您的代码有效(这是一个众所周知的算法),特别是您在保护 LinkedList 方面是正确的,因为它不是内部线程安全的。

However, if you compare your code to the java util implementation http://grepcode.com/file_/repository.grepcode.com/java/root/jdk/openjdk/8u40-b25/java/util/concurrent/ArrayBlockingQueue.java/?v=source it might bring up some points to consider:但是,如果您将代码与 java util 实现http://grepcode.com/file_/repository.grepcode.com/java/root/jdk/openjdk/8u40-b25/java/util/concurrent/ArrayBlockingQueue.java/ 进行比较?v=source它可能会提出一些需要考虑的要点:

  1. please Google for discussions on "ReentrantLock versus Binary Semaphore": They both create a mutex & protect a critical section , but the former better describes your intentions, plus it might be easier for future maintenance.请谷歌讨论“ReentrantLock vs Binary Semaphore”:它们都创建了一个互斥锁并保护了一个关键部分,但前者更好地描述了你的意图,而且它可能更容易在未来维护。 Eg a fellow programmer can't accidentally release a ReentrantLock by a thread that didn't acquire it例如,一个没有获得 ReentrantLock 的线程不会意外地释放 ReentrantLock

  2. Google for discussions on "semaphore versus condition variable" : Both allow you to "wait for something to become available", but condition variable might be more general, plus you can tie all your conditions to a single lock (as the java util code does).谷歌关于“信号量与条件变量”的讨论:两者都允许你“等待某些东西变得可用”,但条件变量可能更通用,而且你可以将所有条件绑定到一个锁(就像 java util 代码那样) )。 I assume this has some minor effect on performance, plus the way you'll need to approach future requirements such as interrupts , timeouts, crashes.我认为这对性能有一些轻微影响,加上您需要处理未来需求的方式,例如中断、超时、崩溃。 This doesn't make your code "wrong", it's just something for you to consider.这不会使您的代码“错误”,这只是您需要考虑的事情。

Without testing, I would say this works.如果没有测试,我会说这是有效的。 However, every release() will notify the thread blocked in acquire().但是,每个release() 都会通知acquire() 中阻塞的线程。 So you really have at least the same cost as a reentrantlock+condition, likely worse because there is 2 acquire and 2 release() calls.所以你真的至少有与可重入锁+条件相同的成本,可能更糟,因为有 2 个获取和 2 个 release() 调用。

Semaphore is another way to achieve mutual exclusion & synchronization.信号量是另一种实现互斥和同步的方式。 A binary semaphore or mutex can be used for locking & unlocking the critical section.二进制信号量或互斥锁可用于锁定和解锁临界区。 A general semaphore or counting semaphore can be used to keep track of free slots & occupied slots.通用信号量或计数信号量可用于跟踪空闲插槽和占用插槽。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM