我对这两个概念有些困惑。
维基百科上锁定自由的定义为:
如果保证整个系统可以进展,则非阻塞算法是无锁定的
非阻塞的定义为:
如果任何线程的失败或暂停不会导致另一个线程的失败或暂停,则称算法为非阻塞
我以为自旋锁是无锁定的,或者至少是非阻塞的。但现在我不确定了。因为根据定义,"自旋锁不是无锁定的"
也对我有意义。例如,如果持有自旋锁的线程被挂起,则会导致在外自旋的其他线程也被挂起。因此,根据定义,自旋锁
即使没有锁定,也不是非阻塞的。
我现在很困惑。有人能清楚地解释一下吗?
我对这两个概念有些困惑。
维基百科上锁定自由的定义为:
如果保证整个系统可以进展,则非阻塞算法是无锁定的
非阻塞的定义为:
如果任何线程的失败或暂停不会导致另一个线程的失败或暂停,则称算法为非阻塞
我以为自旋锁是无锁定的,或者至少是非阻塞的。但现在我不确定了。因为根据定义,"自旋锁不是无锁定的"
也对我有意义。例如,如果持有自旋锁的线程被挂起,则会导致在外自旋的其他线程也被挂起。因此,根据定义,自旋锁
即使没有锁定,也不是非阻塞的。
我现在很困惑。有人能清楚地解释一下吗?
任何可以称为锁的东西(将其他线程从关键部分中排除,直到当前线程解锁)都符合定义,因此不能被称为无锁。是的,自旋锁是一种锁。
如果一个线程在持有锁的同时进入睡眠状态,那么其他线程就无法获取该锁并取得进展,自旋锁无法防止这种情况。操作系统可以随时取消调度一个线程,即使它正在进行关键部分的操作。
请注意,“无锁”并不等同于“无等待”,因此无锁算法仍然可能具有cmpxchg重试循环等内容,但只要一个线程每次都成功,它就是无锁的。
无等待算法甚至不能有这个,最多只能等待缓存失效/争用原子操作的硬件仲裁。维基百科的无阻塞算法文章更详细地定义了无等待和无锁。
我认为你混淆了“阻塞”的两个定义。
我认为你在谈论一个spin_trylock
函数,它尝试获取自旋锁,并在失败时返回错误,而不是自旋等待。因此,在与非阻塞I/O相同的意义下,这是非阻塞的:如果资源不可用,返回错误而不是等待。
这并不意味着系统中的任何线程都在进行受自旋锁保护的进度。这仅仅意味着你的线程可以在尝试获取锁之前做其他事情,而不需要使用单独的线程来并行执行等待获取锁的操作。
在一个无限循环中自旋等待也被认为是阻塞/无法取得进展。按照这个定义,纯自旋锁和通过操作系统辅助休眠等待直到另一个线程解锁的锁之间没有区别。
无锁的定义不涉及浪费CPU时间/电源以腾出空间让独立的工作发生。
有些相关:获取无争用自旋锁不需要系统调用,这意味着它是一种“轻量级”锁。一些锁实现即使在无争用情况下也总是使用(相对较慢的)系统调用。参见Jeff Preshing的Always Use a Lightweight Mutex文章。还要阅读Jeff的其他帖子学习无锁编程,因为它们非常出色。事实上,[lock-free]标签的维基链接到他们。