我想知道是否可以使用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;
}
}
在前面的评论中添加内容-我们可以同意您的代码有效(这是一种众所周知的算法),尤其是您在保护LinkedList方面是正确的,因为它不是内部线程安全的。
但是,如果将代码与java
util实现进行比较,则http://grepcode.com/file_/repository.grepcode.com/java/root/jdk/openjdk/8u40-b25/java/util/concurrent/ArrayBlockingQueue.java/
?v =
source
可能会带来一些要考虑的问题:
请Google进行有关“ ReentrantLock与Binary Semaphore”的讨论:它们都创建了互斥体并保护了 关键部分 ,但是前者可以更好地描述您的意图,并且将来可能更容易维护。例如,同一个程序员不能通过未被获取的线程意外释放ReentrantLock
Google讨论“信号量与条件变量”:两者都允许您“等待某些东西变为可用”,但是条件变量可能更通用,此外,您还可以将所有条件绑定到一个锁(如Java util代码那样) )。我认为这对性能有轻微的影响,另外还有满足未来需求(例如 中断 ,超时,崩溃)的方式。这不会使您的代码“错误”,只是您需要考虑的事情。
2)Java的内置使用了两个锁:takeLock和putLock,并分别用在put()和take()中,我看到间隔队列是一个链表,不是线程安全的,那怎么行呢?
本文向大家介绍详解Java阻塞队列(BlockingQueue)的实现原理,包括了详解Java阻塞队列(BlockingQueue)的实现原理的使用技巧和注意事项,需要的朋友参考一下 阻塞队列 (BlockingQueue)是Java util.concurrent包下重要的数据结构,BlockingQueue提供了线程安全的队列访问方式:当阻塞队列进行插入数据时,如果队列已满,线程将会阻塞等待直
3. 阻塞信号 3.1. 信号在内核中的表示 以上我们讨论了信号产生(Generation)的各种原因,而实际执行信号的处理动作称为信号递达(Delivery),信号从产生到递达之间的状态,称为信号未决(Pending)。进程可以选择阻塞(Block)某个信号。被阻塞的信号产生时将保持在未决状态,直到进程解除对此信号的阻塞,才执行递达的动作。注意,阻塞和忽略是不同的,只要信号被阻塞就不会递达,而忽
阻塞信号是保持该信号并推迟发送,直到阻塞解除,但不会丢失。 结构体sigset_t(信号集合) 其中每一位对应系统支持的一种信号。结构体内部是数组。 函数 函数名 描述 [[sigemptyset sigempty]] 初始化信号集为空集 [[sigfillset sigfillset]] 初始化信号集包含全部信号 [[sigaddset sigaddset]] 向信号集中添加信号 [[sigde
问题内容: 我有一个经典的问题,线程将事件推送到第二个线程的传入队列。仅这次,我对性能非常感兴趣。我要实现的是: 我想要并发访问队列,生产者推送,接收者弹出。 当队列为空时,我希望消费者阻止队列,等待生产者。 我的第一个想法是使用,但是我很快意识到它不是并发的,并且会降低性能。另一方面,我现在使用,但仍要为每个出版物支付/ 的费用。由于使用者在找到空队列时不会阻塞,因此我必须进行同步并处于锁定状态
问题内容: 我在一个非常简单的生产者-消费者场景中使用 java.util.concurrent.BlockingQueue 。例如,此伪代码描述了使用者部分: 到目前为止,一切都很好。在阻塞队列的javadoc中,我读到: BlockingQueue本质上不支持任何类型的“关闭”或“关闭”操作,以指示将不再添加任何项目。这些功能的需求和使用往往取决于实现。例如,一种常见的策略是让生产者插入特殊的