思いつきで書いてみた。動作確認はしてない。 public class LockFreeRingBuffer<E> { int capacity; AtomicReferenceArray array; AtomicInteger head, tail, elements, spaces; public LockFreeRingBuffer(int capacity) { this.capacity = capacity; array = new AtomicReferenceArray(capacity); head = new AtomicInteger(0); tail = new AtomicInteger(0); elements = new AtomicInteger(0); spaces = new AtomicInteger(capacity); } public boolean enqueue(E element) { if (element == null) throw new NullPointerException(); for (;;) { int n = spaces.get(); if (n == 0) return false; if (spaces.compareAndSet(n, n - 1)) break; } int index = head.get(); while (!array.compareAndSet(index % capacity, null, element)) { index++; } head.getAndIncrement(); elements.getAndIncrement(); return true; }
public E dequeue() { for (;;) { int n = elements.get(); if (n == 0) return false; if (elements.compareAndSet(n, n - 1)) break; } int index = tail.get(); E element; for (;;) { element = array.getAndSet(index % capacity, null); if (element != null) break; index++; } tail.getAndIncrement(); spaces.getAndIncrement(); return element; } } もうちょっと減らせないもんかな・・・