Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Lock Free Circular Array

I am thinking about implementing a lock free circular array. One problem is maintaining the head and tail pointers in a lock free manner. The code I have in mind is:

int circularIncrementAndGet(AtomicInteger i) {
    i.compareAndSet(array.length - 1, -1);
    return i.incrementAndGet();
}

Then I would do something like:

void add(double value) {
    int idx = circularIncrementAndGet(tail);
    array[idx] = value;
}

(Note that if the array is full old values will be overwritten, I am fine with that).

Does anyone sees a problem with this design? I suspect there might be a race condition I am not seeing.

like image 767
user1424934 Avatar asked Jan 02 '14 19:01

user1424934


People also ask

What is a wait-free and lock-free circular queue?

The wait-free and lock-free circular queue is a useful technique for time and memory sensitive systems. The wait-free nature of the queue gives a fixed number of steps for each operation.

Is there a lock-free circular buffer?

AFAIK, a lock-free circular buffer has not been invented. The problem will be dealing with the complex condition where a reader overtakes a writer or vis-versa. If you have not spent at least six months studying lock-free data structures, do not attempt to write one yourself.

What is a circulararray in AutoCAD?

The Draft CircularArray command creates an array from a selected object by placing copies along concentric circumferences. The command can optionally create a Link array, which is more efficient than a regular array.

Is array-based lock-free queue thread safe?

7. Conclusions This array based lock-free queue has been proved to work in its 2 versions, the one which is thread safe in multiple producer thread configurations, and the one which is not (the one similar to [11] but allowing multiple consumer threads).


1 Answers

A simpler approach is to use a power of 2 size and do the following.

 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;
 }
like image 96
Peter Lawrey Avatar answered Sep 23 '22 06:09

Peter Lawrey