ConcurrentLinkedQueue 的大小

2022-09-03 02:32:22

阅读Java的ConcurrentLinkedQueue Docs,我想知道为什么实现不可能存储大小:

请注意,与大多数集合不同,size 方法不是常量时间操作。由于这些队列的异步特性,确定当前元素数需要遍历元素。

这种“异步性质”在源中的什么位置?我只看到一个 while 循环来重试排队,直到 AtomicReferences 与预期的值/引用匹配。为什么在成功向队列提供值后无法递增 a?size:AtomicInteger

多谢。


答案 1

假设您有两个线程,一个添加新项,另一个删除项。开始时队列中没有项目。

假设第一个线程添加该项,紧接着另一个线程删除该项并减小大小,此时您的大小为 -1,然后第一个线程将大小递增为 0。

一个稍微人为的示例,但您需要使整个操作成为原子操作,以确保没有其他线程可以访问 -1 的大小。


答案 2

其中一个重要的性能优势来自这样一个事实,即当您更新头部时,您不必担心尾巴,反之亦然,对吧?ConcurrentLinkedQueue

这意味着基本上2个线程可以同时轮询/提供而不会干扰(如果队列大小不是0,那就是)。

如果你有一个柜台,情况并非如此。即使它具有良好的并发性,您仍然会增加CAS操作失败的可能性,因为现在您有这个“热点”,每次进行轮询/提供时都会更新。AtomicInteger

不完全确定作者在说“异步性质”时是否这样说,但我认为这是他们没有像你建议的那样计数器的最大原因。


推荐