首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >自旋锁实现(OSSpinLock)

自旋锁实现(OSSpinLock)
EN

Stack Overflow用户
提问于 2012-10-18 15:12:23
回答 2查看 1.3K关注 0票数 1

我刚刚开始研究多线程编程和线程安全。我熟悉忙等待,经过一些研究,我现在熟悉了自旋锁背后的理论,所以我想我应该看看OSSpinLock在Mac上的实现。它归结为以下函数(在objc-os.h中定义):

代码语言:javascript
复制
static inline void ARRSpinLockLock(ARRSpinLock *l)
{
again:
   /* ... Busy-waiting ... */
    thread_switch(THREAD_NULL, SWITCH_OPTION_DEPRESS, 1);
    goto again;
}

(Full implementation here)

在做了一些研究之后,我现在大概知道了thread_switch的参数是做什么的(this site是我找到它的地方)。我对我读到的内容的解释是,这个对thread_switch的调用将切换到下一个可用的线程,并在1个周期内将当前线程的优先级降低到绝对最小。‘最终’(在CPU时间内)这个线程将再次变得活跃,并立即执行goto again;指令,该指令再次开始忙碌等待。

我的问题是,为什么这个调用实际上是必要的?我发现了另一个自旋锁(这次是针对Windows ) here的实现,它根本不包含(与Windows等效的)线程切换调用。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2012-10-18 15:23:33

我真的不认为他们有什么不同。在第一种情况下:

代码语言:javascript
复制
static inline void ARRSpinLockLock(ARRSpinLock *l)
{
    unsigned y;
again:
    if (__builtin_expect(__sync_lock_test_and_set(l, 1), 0) == 0) {
        return;
    }
    for (y = 1000; y; y--) {
#if defined(__i386__) || defined(__x86_64__)
        asm("pause");
#endif
        if (*l == 0) goto again;
    }
    thread_switch(THREAD_NULL, SWITCH_OPTION_DEPRESS, 1);
    goto again;
}

我们尝试获取锁。如果失败,我们在for循环中旋转,如果在此期间它变得可用,我们立即尝试重新获取它,否则我们放弃CPU。

在另一种情况下:

代码语言:javascript
复制
inline void Enter(void)
{
    int prev_s;
    do
    {
        prev_s = TestAndSet(&m_s, 0);
        if (m_s == 0 && prev_s == 1)
        {
            break;
        }
        // reluinquish current timeslice (can only
        // be used when OS available and
        // we do NOT want to 'spin')
        // HWSleep(0);
    }
    while (true);
}

请注意if下面的注释,它实际上表明,如果操作系统提供该选项,我们可以旋转或放弃CPU。实际上,第二个示例似乎只是将这一部分留给程序员来插入您喜欢的方式来继续这里的代码,因此在某种意义上,它并不像第一个示例那样是一个完整的实现。

我对整个事情的看法是,他们试图在能够快速获得锁(在1000次迭代内)和不占用太多CPU之间取得平衡(因此,如果锁不可用,我们最终会切换)。

票数 1
EN

Stack Overflow用户

发布于 2012-10-18 15:27:44

您可以通过许多不同的方式实现自旋锁。如果你在Windows上找到了另一个SpinLock实现,你会看到另一个算法(它可能涉及到SetThreadPrioritySleepSwitchToThread)。

ARRSpinLockLock的默认实现足够聪明,在第一个旋转周期后,它会在一段时间内“压低”线程优先级,这具有以下优点:

  • 它为拥有释放它的锁的线程提供了更多的机会;
  • 它浪费了更少的CPU时间<>E214>(和<

>E115><代码>E216!)执行NOPPAUSE.

Windows实现没有做到这一点,因为Windows API没有提供这种机会(没有等效的thread_switch()函数,而且对SetThreadPriority 的多次调用可能会降低的效率)。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/12949028

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档