什么是非无锁的无阻塞算法示例?

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)无锁算法

非阻塞同步算法与CAS(Compare and Swap)无锁算法

提升--06---解析Synchronized锁升级

无锁编程

SQLSERVER 的 nolock 到底是怎样的无锁

java锁优化