我刚刚开始研究多线程编程和线程安全。我熟悉忙等待,经过一些研究后我现在熟悉自旋锁背后的理论,所以我想我应该看看 OSSpinLock 在 Mac 上的实现。它归结为以下函数(在 objc-os.h 中定义):
static inline void ARRSpinLockLock(ARRSpinLock *l)
{
again:
/* ... Busy-waiting ... */
thread_switch(THREAD_NULL, SWITCH_OPTION_DEPRESS, 1);
goto again;
}
经过一些挖掘,我现在对 thread_switch
的参数做了什么有了大概的了解(this site 是我找到它的地方)。我对所读内容的解释是,对 thread_switch 的这个特定调用将切换到下一个可用线程,并将当前线程的优先级降低到绝对最小值 1 个周期。 “最终”(在 CPU 时间内)该线程将再次激活并立即再次执行 goto;
指令,这会再次开始忙等待。
但我的问题是,为什么这个调用实际上是必要的?我找到了自旋锁的另一个实现(这次是针对 Windows)here而且它根本不包括(Windows 等效的)线程切换调用。
最佳答案
您可以通过多种不同的方式实现自旋锁。如果您找到另一个适用于 Windows 的 SpinLock
实现,您会看到另一个算法(它可能涉及 SetThreadPriority
、Sleep
或 SwitchToThread
)。
ARRSpinLockLock
的默认实现足够聪明,在第一个旋转周期后,它会暂时“降低”线程优先级,这具有以下优点:
- 它给拥有锁的线程更多机会释放它;
- 它在执行
NOP
或PAUSE
时浪费更少的 CPU 时间(和功率!)。
Windows 实现不这样做,因为 Windows API 不提供那个机会(没有等效的 thread_switch()
函数和对 SetThreadPriority
的多次调用 可能会效率较低)。
关于c - 自旋锁实现 (OSSpinLock),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12949028/