在多线程(2线程)程序中,我有这段代码:
while(-1)
{
m.lock();
(...)
m.unlock();
}
m
是一个互斥锁(在我的例子中是一个c ++ 11 std::mutex
,但我认为如果我使用不同的库,它就不会改变。)
假设第一个线程拥有互斥锁并且它在(...)
部分中完成了某些操作。第二个线程试图获取互斥锁,但它正在等待第一个线程释放m
。
问题是:当线程1结束它(...)
执行并解锁互斥锁时,我们可以确定线程2获取互斥锁,或者线程1可以在线程2之前再次重新获取互斥锁,使其停留在lock()
?
答案 0 :(得分:4)
C ++标准不保证授予互斥锁的订单锁定。因此,活动线程完全有可能保持unlock()
和lock()
std::mutex m
,而没有另一个线程尝试获取锁定。我不认为C ++标准提供了一种控制线程优先级的方法。我不知道你想要做什么,但可能有另一种方法可以避免你遇到的问题。
答案 1 :(得分:3)
如果两个线程都具有相同的优先级,那么标准互斥实现就没有这样的保证。有些操作系统有“谁在等待”,并且在你发布内容时会选择“最长等待”,但这是一个实现细节,而不是你可以依赖的东西。
想象一下,你有两个线程,每个线程运行如下:
m.lock();
(...)
m.unlock();
(...) // Clearly not the same code as above (...)
m.lock();
(...) // Some other code that needs locking against updates.
m.unlock();
您是否希望上面的代码每次都在第二个锁上切换线程?
顺便说一下,如果两个线程都为整个循环运行锁定,那么锁定的重点是什么?
答案 2 :(得分:1)
没有任何保证,因为线程没有以任何方式相互排序。实际上,唯一的同步点是互斥锁定。
如果第一个线程在紧密循环中运行该函数,则完全有可能立即重新获取锁。如果任何线程在互斥锁上休眠,则典型的实现具有通知和唤醒机制,但是也可能存在让正在运行的线程继续而不是执行上下文切换的偏见...这非常取决于实现和细节当时的平台。
答案 3 :(得分:1)
C ++或底层操作系统不提供任何保证。
然而,通过到关键区域的线程到达时间(在这种情况下为互斥)确定了一些合理的公平程度。这种公平性可以表示为统计概率,但不是严格保证。很可能这个选择将归功于OS执行调度程序,它还将考虑许多其他因素。
答案 4 :(得分:-1)
依靠这样的代码并不是一个好主意,所以你应该改变你的设计。 但是,在某些操作系统上,sleep(0)将产生线程。 (在Windows上睡眠(0)) 同样,最好不要依赖它。