什么是非无锁的无阻塞算法示例?
Posted
技术标签:
【中文标题】什么是非无锁的无阻塞算法示例?【英文标题】:What is an example of obstruction-free algorithm that is not lock-free? 【发布时间】:2017-09-29 13:25:57 【问题描述】:所以 lock-freedom 是当您保证整个系统取得进展时,尽管某些线程可能会饿死。所以基于 CAS 的实现可以提供这种保证。
那么无阻塞是当所有其他线程都被挂起时,一个线程可以保证完成。
你能举一个不无锁的无阻塞算法的简单例子吗?
谢谢!
【问题讨论】:
整个算法必须是无锁的,而不是每个单独的 CAS。 (en.wikipedia.org/wiki/Non-blocking_algorithm)。例如,请参阅使用原子 CAS 对无锁队列的分析,它甚至不是无阻塞的(尽管在实践中它非常好并且在低争用情况下可以很好地扩展)。 ***.com/questions/45907210/…. 【参考方案1】:我推荐阅读 introduced the term 的论文 - 主要作者 Herlihy 在 25 年前引入 wait-freedom 的概念时开创了整个行业。
无锁和无阻塞之间的核心区别在于,如果两个或多个线程正在运行,后者不保证进度(但如果只有一个在运行)。
论文的内容是你想要的,一个无阻塞但不是无锁的出列示例。
为了更简单,我将描述一个基于数组的堆栈,它以相同的方式运行,并且是无阻塞但不是无锁的。
想象一个在数组顶部实现的堆栈,这样堆栈的零个或多个元素连续存储在数组的开头,然后是所有剩余位置的“空”元素。堆栈的每个元素都存储为一个元组:(val, seq)
,其中val
是用户提供的值,seq
是一个序列号,它是算法的关键(同时也避免了 ABA 问题1 )。
要将元素压入堆栈,首先要找到堆栈中的最后一个元素(位置A[k-1]
),它直接位于第一个null 元素之前(位置A[k]
)。您尝试使用 CAS 增加 A[k-1]
的序列号(元素不会更改),如果成功,您尝试同时替换位置 A[k]
处的空元素的值并增加其序列号。如果任一 CAS 失败,请重试。
pop 算法类似,但以相反的顺序处理元素(增加第一个 null 元素的序列号,然后尝试使最后一个元素为 null 并增加其序列号)。
这个结构的正确性在上面的论文中有更详细的描述,但基本上通过成功增加A[k-1]
th 元素,您可以确保此时它仍然是列表中的最后一个元素,并且您同时通知任何通过导致初始 CAS 失败,您可以“获得下一个镜头”的竞速推进操作。如果第二个 CAS 成功,则您成功添加了一个元素。
请注意,并发的 push 和 pop 操作可能会导致彼此无限期地失败。 push 线程递增A[k-1]
,pop 递增A[k]
,然后每个线程都失败了,因为它们看到了另一个线程的增量。冲洗并重复。这是活锁的一个例子。
请注意,如果只有一个线程在运行,问题就会消失,这是无阻塞的关键观察。
1 ...它还避免了完整版本的出队中的“环绕”问题,但我认为堆栈不会发生这种情况。
【讨论】:
感谢您的详细解答!不过,我不明白元组的 seq 组件包含什么。你能更好地解释那部分吗? 只是一个足够大的整数,它不会“轻易”环绕。完整的细节在论文中。 @vidi【参考方案2】:我不确定是否可以给出一个简单的例子。简单的事情通常是无等待的(例如 RCU 的读取器端)或无锁的(例如不可能活锁的 CAS 重试循环),甚至不是无阻塞的。
请参阅Lock-free Progress Guarantees,了解对无锁多写入器多读取器队列的分析,其中在操作中间休眠的写入器可能会阻塞整个队列,尽管它具有高性能/低争用且在实践中很有用。
我认为只有当线程可以取消其他线程的部分完成操作时,才可能实现无阻塞而不无锁。 (从而处理在他们醒来时取消自己的操作的情况)。我可能弄错了;也许还有其他方法可以使算法成为非阻塞但不是无锁的。
这不是我认为的简单,但https://en.wikipedia.org/wiki/Non-blocking_algorithm 说:
一些无障碍算法在数据结构中使用一对“一致性标记”。读取数据结构的进程首先读取一个一致性标记,然后将相关数据读入内部缓冲区,然后读取另一个标记,然后比较标记。如果两个标记相同,则数据是一致的。当读取被另一个更新数据结构的进程中断时,标记可能是不相同的。在这种情况下,进程会丢弃内部缓冲区中的数据并重试。
如果争用的退避算法不好,这可能会发生活锁。由于有太多的线程在敲击它,他们可以在任何事情完成之前不断地相互取消。这就是它不是无锁的原因。
【讨论】:
以上是关于什么是非无锁的无阻塞算法示例?的主要内容,如果未能解决你的问题,请参考以下文章
非阻塞同步算法与CAS(Compare and Swap)无锁算法