对于我的一个必须支持并发读取和写入的项目,我需要一个能够缓冲项的容器,直到使用者一次获取每个当前缓冲的项。由于生产者应该能够生成数据,而不管消费者是否读取当前缓冲区,我提出了一个自定义实现,在的帮助下,将每个条目添加到支持中,直到执行翻转,这会导致当前条目被返回,同时存储具有空队列和元数据的新条目以原子方式存储在该中。AtomicReferenceConcurrentLinkedQueueAtomicReference
我想出了一个解决方案,例如
public class FlippingDataContainer<E> {
private final AtomicReference<FlippingDataContainerEntry<E>> dataObj = new AtomicReference<>();
public FlippingDataContainer() {
dataObj.set(new FlippingDataContainerEntry<>(new ConcurrentLinkedQueue<>(), 0, 0, 0));
}
public FlippingDataContainerEntry<E> put(E value) {
if (null != value) {
while (true) {
FlippingDataContainerEntry<E> data = dataObj.get();
FlippingDataContainerEntry<E> updated = FlippingDataContainerEntry.from(data, value);
if (dataObj.compareAndSet(data, updated)) {
return merged;
}
}
}
return null;
}
public FlippingDataContainerEntry<E> flip() {
FlippingDataContainerEntry<E> oldData;
FlippingDataContainerEntry<E> newData = new FlippingDataContainerEntry<>(new ConcurrentLinkedQueue<>(), 0, 0, 0);
while (true) {
oldData = dataObj.get();
if (dataObj.compareAndSet(oldData, newData)) {
return oldData;
}
}
}
public boolean isEmptry() {
return dataObj.get().getQueue().isEmpty();
}
}
由于其他线程在此线程可以执行更新之前更新值可能会导致可能的重试,因此我需要在每次写入尝试时复制实际队列,否则即使原子引用无法更新,也会将条目添加到共享队列中。因此,只需将值添加到共享队列中,就可能导致值条目多次添加到队列中,而实际上它只应出现一次。
虽然与复制队列的代码相比,这允许运行测试的速度快10倍以上,但它也经常无法通过消耗测试,因为现在,在消费者线程翻转队列并处理数据之后,可能会立即将值元素添加到队列中,因此并非所有项目似乎都被消耗了。
现在的实际问题是,是否可以避免复制后备队列以获得性能提升,同时仍然允许使用无锁算法原子地更新队列的内容,从而避免中途丢失一些条目?
梦里花落0921
三国纷争
MYYA
随时随地看视频慕课网APP
相关分类