我想知道是否可以使用AtomicReferenceArray替代ConcurrentLinkedQueue(如果可以使用有限结构)。
我目前有类似的东西:
ConcurrentLinkedQueue<Object[]> queue = new ConcurrentLinkedQueue<Object[]>();
public void store(Price price, Instrument instrument, Object[] formats){
Object[] elements = {price, instrument, formats};
queue.offer( elements);
}
store(..)由多个线程调用。
我还有一个使用者线程,该线程会定期唤醒并使用这些元素。
private class Consumer implements Runnable{
@Override
public void run(){
List<Object[]> holder = drain( queue );
for(Object[] elements : holder ){
for( Object e : elements ){
//process ...
}
}
private final List<Object[]> drain(){
//...
}
}
我可以换掉ConcurrentLinkedQueue以便使用AtomicReferenceArray并仍然保持线程安全性吗?
具体来说,原子地存储元素并建立“先发生”关系,以便使用者线程看到不同线程存储的所有元素吗?
我尝试阅读AtomicReferenceArray的源代码,但仍不确定。
干杯
最佳答案
AtomicReferenceArray
可用作无锁定的单个使用者/多生产者环形缓冲区。几个月前,我在experimenting处实现,并且有一个可以正常工作的原型。这样做的好处是减少了垃圾的创建,更好的缓存局部性,并且由于更简单而没有满时的性能也更好。缺点是缺乏严格的fifo语义,并且当缓冲区已满时性能很差,因为生产者必须等待流失发生。可以通过回退到ConcurrentLinkedQueue
以避免停顿来缓解这种情况。
制片人必须看到事前发生的边缘,以便他们获得唯一的广告位。但是,由于只需要一个消耗器,因此可以将其延迟到排空完成为止。在我的用法中,消耗在线程之间摊销,因此通过成功获取尝试锁来选择使用者。该锁的释放提供了优势,从而允许阵列更新在关键部分内使用惰性集。
我只会在对性能进行高度调整的特殊情况下使用此方法。在我的用法中,将其作为缓存的内部实现细节是有意义的。不过,我一般不会使用它。