无锁圆阵

use*_*934 5 java circular-buffer lock-free

我正在考虑实现一个无锁的圆形数组.一个问题是以无锁的方式保持头部和尾部指针.我想到的代码是:

int circularIncrementAndGet(AtomicInteger i) {
    i.compareAndSet(array.length - 1, -1);
    return i.incrementAndGet();
}
Run Code Online (Sandbox Code Playgroud)

然后我会做类似的事情:

void add(double value) {
    int idx = circularIncrementAndGet(tail);
    array[idx] = value;
}
Run Code Online (Sandbox Code Playgroud)

(注意,如果数组是完整的旧值将被覆盖,我很好).

有没有人发现这个设计有问题?我怀疑可能存在我没有看到的竞争状况.

Pet*_*rey 5

更简单的方法是使用 2 的幂并执行以下操作。

 final double[] array;
 final int sizeMask;
 final AtomicInteger i = new AtomicInteger();

 public CircularBuffer(int size) {
      assert size > 1 && ((size & (size -1)) == 0); // test power of 2.
      array = new double[size];
      sizeMask = size -1;
 }

 void add(double value) {
     array[i.getAndIncrement() & sizeMask] = value;
 }
Run Code Online (Sandbox Code Playgroud)

  • 如果增量发生在之前,我们如何确定对数组的最后一次写入将是可见的? (2认同)