生产与消费流程
生产者
下面忽略数组的环形结构,介绍一下如何实现无锁设计。整个过程通过原子变量
单个生产者
生产者单线程写数据的流程比较简单:
- 申请写入
m 个元素; - 若是有
m 个元素可以入,则返回最大的序列号。这儿主要判断是否会覆盖未读的元素; - 若是返回的正确,则生产者开始写入元素。

多个生产者
多个生产者的情况下,会遇到“如何防止多个线程重复写同一个元素”的问题。
但是会遇到一个新问题:如何防止读取的时候,读到还未写的元素。
读数据
消费者多线程读取的情况会复杂很多:
- 申请读取到序号
n ; - 若
writer cursor >= n ,这时仍然无法确定连续可读的最大下标。从reader cursor 开始读取available Buffer ,一直查到第一个不可用的元素,然后返回最大连续可读元素的位置; - 消费者读取元素。
如下图所示,读线程读到下标为
然后,消费者读取下标从

写数据
多个生产者写入的时候:
- 申请写入
m 个元素; - 若是有
m 个元素可以写入,则返回最大的序列号。每个生产者会被分配一段独享的空间; - 生产者写入元素,写入元素的同时设置
available Buffer 里面相应的位置,以标记自己哪些位置是已经写入成功的。
如下图所示,

防止不同生产者对同一段空间写入的代码,如下所示:
public long tryNext(int n) throws InsufficientCapacityException
{
if (n < 1)
{
throw new IllegalArgumentException("n must be > 0");
}
long current;
long next;
do
{
current = cursor.get();
next = current + n;
if (!hasAvailableCapacity(gatingSequences, n, current))
{
throw InsufficientCapacityException.INSTANCE;
}
}
while (!cursor.compareAndSet(current, next));
return next;
}
通过