Java 中的无锁和大小限制队列



根据这篇文章,我正在尝试扩展Java中无锁队列的实现。

对于我的实现,我被限制只能使用原子变量/引用。另外,我的队列应该有一个最大大小。因此,当队列已满时,putObject() 应该阻塞,如果队列为空,则应该阻塞 getObject()。

目前我不知道如何在不使用锁的情况下解决这个问题。

例如,当使用 AtomicInteger 时,修改操作将是原子的。但是仍然存在一个问题,我必须在 putObject() 和 getObject() 中处理检查和修改情况,对吗?因此,仍然存在排队线程在检查当前队列大小后会中断的情况。

我目前的问题是,通过我当前的限制,这个问题是否可以解决?

迎接

如果您有一个可行的、正常工作的无锁队列,那么添加最大大小就像添加一个 AtomicInteger 并在正确的时间进行检查一样简单。

添加元素时,您基本上预先保留队列中的位置。像这样:

while (true) {
    int curr = count.get();
    if (curr < MAX) {
        if (count.compareAndSet(curr, curr + 1)) {
            break;
        }
    }
    else {
        return FULL;
    }
}

然后添加新元素并将其链接。获取时,您可以像往常一样访问头部并检查是否有任何内容可以从队列中返回。如果是,则返回它,然后减少计数器。如果没有,则只需返回空。请注意,我没有使用计数器来检查队列是否真的为空,因为计数器可能是 1,而由于预保留方法,还没有链接到队列中的内容。所以我只是相信你的队列有办法告诉你"我里面有东西"(它必须,或者 get() 永远不会起作用)。

这是一个非常常见的问题,通常通过使用环形缓冲区来解决。 这是网络适配器使用的,中断器库也是如此。 我建议你看看Disruptor,以及一个关于你可以用环形缓冲区做什么的很好的例子。

最新更新