如果不为空则锁定空闲队列入队
我已经使用基于 http://www.boyet 的比较和交换在 C 中实现了无锁队列。 com/articles/LockfreeQueue.html。
它工作得很好,但我正在尝试将此队列集成到我已经实现的无锁跳过列表中。我使用跳过列表作为优先级队列,并希望在发生优先级冲突时使用每个节点内的无锁队列来存储多个值。但是,由于当我检测到优先级冲突时在跳过列表中管理节点的方式,仅当队列不为空时,我才需要能够将项目添加到队列中。
由于队列的无锁性质,我不确定如何实际执行此操作。
那么基本上我将如何编写原子 enqueue_if_not_empty 操作?
I have implemented a lock free queue in C using compare and swap based on http://www.boyet.com/articles/LockfreeQueue.html.
Its working great but I'm trying to integrate this queue into a lock free skip-list that i have implemented. I'm using the skip-list as a priority queue and would like to use the lock free queue inside each node to store multiple values when there is a priority collision. however due to the way nodes are managed in the skip list when i detect a priority collision i need to be able to add the item to the queue only if the queue is not empty.
due to the lock free nature of the queue im not sure how to actually perform this operation.
So basically how would i write an atomic enqueue_if_not_empty operation?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
编辑:正如人们所注意到的,我用完全相反的语义编写了该函数 - 仅排队到一个空队列中。我修改了名称以反映这一点,并决定保留原样,以防万一有人感兴趣。因此,这不是问题的正确答案,但请不要投反对票,除非您找到其他原因:)
下面是尝试将
EnqueueIfEmpty()
添加到引用论文中的队列实现中。我没有验证它是否有效,甚至没有编译。基本思想是,在 head 之后插入一个新节点(而不是尾部),前提是 head 的下一个节点当前为 null(这是空队列的必要条件)。我留下了额外的检查来检查头部是否等于尾部,这可能可以被删除。
EDIT: As it was noticed, I wrote the function with quite the opposite semantics - enqueuing only into an empty queue. I fixed the name to reflect that, and decided to leave it as is just in case someone will be interested. So, this is not the right answer to the question, but do not downvote please, unless you find another reason :)
Below is an attempt to add
EnqueueIfEmpty()
to the queue implementation in the referenced paper. I did not verify that it works or even compiles.The basic idea is that you insert a new node right after the head (and not the tail), provided that head's next is currently null (which is the necessary condition for an empty queue). I left additional checks for head being equal to tail, which possibly can be removed.
Enqueue-If-Not-Empty 看起来相对简单,但有一个限制:其他线程可能同时从队列中删除所有先前的项目,因此在尾部插入完成后,新项目可能恰好是队列中的第一个。由于原子比较和交换操作是使用不同的字段完成的(入队更改
tail.Next
而出队则推进head
),因此更强的保证不仅需要在此函数中增加复杂性但至少在Dequeue()
中也是如此。对普通
Enqueue()
方法进行以下更改就足够了:1) 在函数开始时,检查
head.Next
是否为空,如果是,则立即返回,因为队列为空。2) 将
head.Next!=null
添加到循环条件中,以防在插入成功之前初始非空队列变空时应停止入队尝试。这并不能阻止我上面描述的情况(因为在检查空性和节点插入之间存在一个时间窗口),但减少了其发生的机会。3)在函数末尾,只有在新节点成功入队时才尝试推进尾部(就像我在 Enqueue-If-Empty 答案中所做的那样)。
Well, Enqueue-If-Not-Empty appears to be relatively straightforward, but with a limitation: other threads may concurrently remove all previous items from the queue, so that after insertion at the tail is done, the new item might happen to be the first in the queue. Since atomic compare-and-swap operations are done with different fields (enqueuing changes
tail.Next
while dequeuing advanceshead
), stronger guarantees would require additional complexity not only in this function but at least inDequeue()
as well.The following changes to the normal
Enqueue()
method are sufficient:1) at the function start, check for
head.Next
being null, and if so, return immediately as the queue is empty.2) add
head.Next!=null
into the loop condition in case enqueuing attempts should be stopped if the initially non-empty queue becomes empty before insertion succeeds. This does not prevent the situation I descibed above (because there is a time window between the check for emptiness and the node insertion), but reduces its chance to happen.3) at the end of the function, only try advancing the tail if the new node was successfully enqueued (like I did in the Enqueue-If-Empty answer).