与互斥锁相比,自旋锁是否保证上下文切换

Do spinlocks guarantee context switching when compared to mutexes

考虑以下代码片段

int index = 0;
av::utils::Lock lock(av::utils::Lock::EStrategy::eMutex); // Uses a mutex or a spin lock based on specified strategy.

void fun()
{
    for (int i = 0; i < 100; ++i)
    {
        lock.aquire();
        ++index;
        std::cout << "thread "  << std::this_thread::get_id() << " index = " << index << std::endl;
        std::this_thread::sleep_for(std::chrono::milliseconds(500));
        lock.release();
    }
}

int main()
{
    std::thread t1(fun);
    std::thread t2(fun);

    t1.join();
    t2.join();
}

我使用用于同步的互斥量获得的输出是第一个线程 1 完全执行,然后是线程 2。 在使用自旋锁(使用 std::atomic_flag 实现)时,我得到交错的线程之间的执行顺序(线程 1 的一次迭代后跟线程 2 的另一次迭代)。后一种情况的发生与我在执行迭代时添加的延迟无关。

我明白互斥量只保证互斥,不保证执行顺序。我的问题是,如果我想要一个执行顺序,使两个线程以交错方式执行,使用自旋锁是否是推荐的策略?

The output that I get with a mutex ... is first thread 1 [runs through the whole loop] followed by thread 2.

那是因为你的循环使用锁的方式:循环体做的最后一件事是解锁锁。它在下一次迭代开始时所做的下一件事是,它再次锁定锁。

另一个线程可以被阻塞,有效休眠,等待互斥体。当您的线程 1 释放锁时,OS 调度程序可能仍然是 运行 它的算法,试图弄清楚当线程 1 出现并再次锁定锁时如何响应。

这就像一场锁定互斥量的比赛,枪响时线程1在起跑线上,而线程2坐在板凳上系鞋带。

While using a spinlock...the order of execution between the threads which is interleaved

那是因为 "blocked" 线程并没有真正被阻塞。它在等待时仍在不同的处理器上活跃 运行。当第一个线程释放它时,它有更好的机会赢得锁。