multithreading - 自旋锁是免费的吗?

标签 multithreading lock-free spinlock

我对这两个概念有点困惑。

维基上无锁的定义:

A non-blocking algorithm is lock-free if there is guaranteed system-wide progress



非阻塞的定义:

an algorithm is called non-blocking if failure or suspension of any thread cannot cause failure or suspension of another thread



我认为自旋锁是无锁的,或者至少是非阻塞的。但现在我不确定。因为根据定义,"spinlock is not lock-free"对我来说也很有意义。就像,如果持有自旋锁的线程被挂起,那么它会导致其他在外面旋转的线程被挂起。所以,根据定义,spinlock甚至不是非阻塞的,更不用说无锁了。

我现在很困惑。谁能解释清楚?

最佳答案

任何可以称为锁的东西(在当前线程解锁之前从临界区中排除其他线程)都不是无锁的。是的,自旋锁是一种锁。

如果一个线程在持有锁时休眠,则没有其他线程可以获取它并向前推进,而自旋锁无法阻止这种情况。操作系统可以随时取消调度线程,即使它处于临界区的中间。

请注意,“无锁”与“无等待”不同,因此无锁算法仍然可以有像 cmpxchg 重试循环这样的东西,但只要一个线程每次都成功,它就是无锁的。

无等待算法甚至不能做到这一点,最多必须等待竞争原子操作的缓存未命中/硬件仲裁。维基百科的non-blocking algorithm article更详细地定义了无等待和无锁。

我认为您混淆了“阻塞”的两个定义。

我认为您在谈论 spin_trylock尝试获取自旋锁的函数 , 如果它失败而不是旋转,则返回错误。因此,这是与非阻塞 I/O 相同意义上的非阻塞:因错误而失败,而不是等待资源可用性。

这并不意味着系统中的任何线程在受自旋锁保护的事物上取得进展。 这只是意味着您的线程可以在再次尝试之前去做其他事情,而不是需要使用单独的线程来与等待获取锁并行执行某些操作。

在无限循环中旋转算作阻塞/不进展。对于这个定义,纯自旋锁和(在操作系统帮助下)休眠直到另一个线程解锁的自旋锁之间没有区别。

无锁的定义与浪费 CPU 时间/功率来为独立工作腾出空间无关。

有点相关:获取无竞争的自旋锁不需要系统调用,这意味着它是一个“轻量级”锁。即使在无竞争的情况下,一些锁实现也总是使用(相对较慢的)系统调用。见 Jeff Preshing's Always Use a Lightweight Mutex文章。另请阅读 Jeff 的其他帖子以了解有关无锁编程的更多信息,因为它们非常出色。事实上,[无锁] 标签维基链接到它们非常好。

关于multithreading - 自旋锁是免费的吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41146527/

相关文章:

ios - 如何使dispatch_after和dispatch_semaphore_t在GCD中一起工作?

c# - Thrift 非阻塞服务器 c#

linux-kernel - 为什么 perf 总是显示 _raw_spin_unlock_irqrestore 或其他一些自旋解锁功能

c - 我的自旋锁实现是否正确且最佳?

linux - 持有信号量的代码可以被抢占是什么意思

java - 多线程java中的重复输出

c# - WPF 文本框性能

c++ - 带 bo​​ost::atomic 的无锁队列——我这样做对吗?

c++ - 加载或存储可以在有条件之前重新排序吗?

java - 无锁算法中的ABA