与互斥锁相比,旋转锁可以保证上下文切换

Do spinlocks guarantee context switching when compared to mutexes

本文关键字:旋转 上下文切换      更新时间:2023-10-16

考虑以下代码片段

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。在使用spinlock(使用std::atomic_flag实现(时,我得到了交错的线程之间的执行顺序(线程1的一次迭代,然后是线程2的另一次迭代(。后一种情况发生,与我在执行迭代时添加的延迟无关。

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

我用互斥体得到的输出。。。是第一个线程1[贯穿整个循环],然后是线程2。

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

另一个线程可以被阻塞,有效地休眠,等待互斥。当线程1释放锁时,操作系统调度程序可能仍在运行其算法,试图找出如何在线程1再次锁定时对此做出响应。

这就像是一场锁定互斥锁的比赛,当枪声响起时,线程1在起跑线上,而线程2坐在替补席上,系鞋带。

使用旋转锁时。。。交织的线程之间的执行顺序

这是因为"被阻塞"的线程并没有真正被阻塞。在等待期间,它仍在另一个处理器上运行。当第一个线程释放它时,它有更好的机会赢得锁定。