我有一个我实现的fifo队列,它有两个方法add()
和remove()
,它们都在队列上执行写操作。为了使其线程安全,我正在使用ReentrantLock
。我有两个条件,(i)如果队列为空并且试图删除,则阻塞一个线程; (ii)如果队列已满并且尝试添加,则阻塞线程。现在,我想实现一个peek操作,它允许多个线程同时执行peek,但没有线程能够写入。如果我使用ReentrantLock
我无法实现,因为我必须获得锁并且它是互斥的。我可以在ReentrantReadWriteLock
中进行查看操作,但它没有我需要的条件变量。有什么建议吗?
答案 0 :(得分:0)
为什么peek()
需要锁定?
peek()
不可能提供有保证的正确答案。
if (q.peek() != NULL) {
... q could be empty at this point because some other consumer
could have removed the last item after the peek() returned...
} else {
... q could be non-empty at this point because a consumer could
have added new items after the peek() returned...
}
如果只有一个使用者,那么peek()方法会更有用。在那种情况下:
if (q.peek() != NULL) {
...q MUST be non-empty here, because there is no other thread that
could have removed anything from the queue...
}
当然,peek()可能需要锁定的一个原因是你实现了一个链接的队列。在这种情况下,您可能需要锁定以防止peek()方法跟踪错误的指针并使程序崩溃。
答案 1 :(得分:0)
如果您只是在寻找解决方案,快速解决方法是在释放锁之前创建重复数组(队列),但在每次更新之后。这个数组可能是peek()的引用变量。
我不确定java是否在线程时支持这个,但你可以创建另一个变量,比如查询,它是对原始队列的引用。这将允许您立即查看peek()的更新。虽然我在Java方面略显新手,但大多数语言通过使用以下内容实现此目的:
query = &queue;
& sign是引用运算符的传递。