这个问题是由无锁进度保证提出的。所示的代码并不是完全无锁的。当队列不为空或未满时,每当挂起写入线程时,读取器线程将返回false,从而阻止整个数据结构取得进展。
对于真正无锁的环形缓冲区,正确的行为应该是什么?
通常,真正的无锁算法涉及一个阶段,其中一个抢占线程实际上试图帮助另一个线程完成一个操作。
有提到这种技术吗?如何为基于数组的MPMC队列实现?
我看了一些代码,它们也有类似的问题。
发布于 2022-04-03 16:01:39
作为一个很好的例子,说明了跨线程辅助在实际生活中是如何工作的,请考虑通过按照以下思路更改liblfds
算法可以获得一个无锁的MPMC队列:
使用3个柜台:
alloc_pos
:已经启动的推送操作的总数。当推送开始时,这会以原子方式递增。write_pos
:所有较低位置的写操作都已完成。read_pos
:所有写在较低位置的物品都已经被消耗掉了。在此方案中,由一个CAS在受影响的插槽中完成推送或pop操作。write_pos
和read_pos
变量是多余的。
因此,要推送,线程首先递增alloc_pos
,然后将write_pos
递增到它前面的所有插槽,它可以看到这些插槽是完整的。这是一个帮助--它正在完成以前在其他线程中启动的写操作。然后,线程必须扫描write_pos
和alloc_pos
之间的插槽,直到找到空闲的时隙,并设法将其保留在CAS中。
要弹出,读取器首先将read_pos
增加到它可以看到的较低位置上的所有项目被消耗。再一次,这是一个帮助--完成先前的阅读。然后,它从read_pos
扫描到alloc_pos
,看看是否能够找到正在编写的项目。
正如注释中提到的那样,真正做到这一点很烦人,实现决策会牺牲性能,从而保证您需要的订单和可用性,以及跳过圈来防止ABA问题。
https://stackoverflow.com/questions/71725753
复制相似问题