最簡單和經典的解決方案是覆蓋最老元素的有界環形緩衝區。
實現相當簡單。您需要一個AtomicInteger/Long for index + AtomicReferenceArray,並且您有一個無鎖通用堆棧,僅有兩種方法offer/poll
,no size()
。大多數併發/無鎖結構有w/size()的困難。非覆蓋堆棧可以具有O(1),但是具有put上的分配。
東西沿着線:
package bestsss.util;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.AtomicReferenceArray;
public class ConcurrentArrayStack<E> extends AtomicReferenceArray<E>{
//easy to extend and avoid indirections,
//feel free to contain the ConcurrentArrayStack if feel purist
final AtomicLong index = new AtomicLong(-1);
public ConcurrentArrayStack(int length) {
super(length); //returns
}
/**
* @param e the element to offer into the stack
* @return the previously evicted element
*/
public E offer(E e){
for (;;){
long i = index.get();
//get the result, CAS expect before the claim
int idx = idx(i+1);
E result = get(idx);
if (!index.compareAndSet(i, i+1))//claim index spot
continue;
if (compareAndSet(idx, result, e)){
return result;
}
}
}
private int idx(long idx){//can/should use golden ratio to spread the index around and reduce false sharing
return (int)(idx%length());
}
public E poll(){
for (;;){
long i = index.get();
if (i==-1)
return null;
int idx = idx(i);
E result = get(idx);//get before the claim
if (!index.compareAndSet(i, i-1))//claim index spot
continue;
if (compareAndSet(idx, result, null)){
return result;
}
}
}
}
最後音符:具有模操作 是一個昂貴和功率爲2的容量是優選的,經由&length()-1
(也守衛VS長溢出)。
」非阻塞 - 如果雙端隊列爲空,則檢索不應該阻塞,它也不應該返回null/throw異常是雙端隊列已滿。 - 從空列表中檢索項目時會發生什麼?既不例外,也不阻塞,也不返回'null'?可以返回 – 2010-10-23 09:15:45
檢索'null'。如果deque是_full_,那麼應該添加該項目,並且舊項目 - 丟棄 – Bozho 2010-10-23 09:24:30
只是一個說明LinkedBlockingDeque不是併發的。 – bestsss 2011-12-06 18:40:54