使用多个std::unique_lock加锁互斥量时,等待线程是否遵循FIFO规则执行?
C++ std::mutex 多线程调度问题解答
- 释放mutex后哪个线程会优先拿到锁?
标准C++没有对std::mutex的调度规则做强制规定,具体行为完全由操作系统调度策略、标准库的实现决定,没有统一的通用答案。你给出的示例里三个线程的抢锁顺序是完全不确定的,每次运行结果都可能不一样。 - 调度是否遵循FIFO规则?
默认实现基本都不遵循FIFO。C++标准没有要求普通std::mutex是公平锁,主流的gcc、MSVC的STL实现里的普通互斥量都是非公平设计,锁释放时不会按线程开始等待的先后顺序分配锁。 - 会不会出现线程永久饥饿的问题?
极端的永久饥饿几乎不会出现,主流操作系统的线程调度都会给等待时间更长的线程动态提升调度优先级,避免完全抢不到资源的情况。但高频率抢锁的场景下,完全可能出现单个线程连续多次抢不到锁、等待时长远高于其他线程的情况。如果你的业务对锁的获取公平性有要求,不要依赖默认std::mutex的行为。 - 等待线程会不会放在有序队列里?排序规则是什么?
普通std::mutex没有强制要求维护有序等待队列,就算部分底层实现有队列,排序规则也没有统一标准:- 部分操作系统的互斥量实现会结合线程优先级、等待时长排序
- 还有不少实现为了提升性能,唤醒时优先选择当前正在CPU上运行的线程,减少上下文切换开销,完全不考虑等待先后
如果业务要求必须按FIFO顺序获取锁,可以自己基于std::condition_variable实现公平排队逻辑,或者使用带公平属性的互斥量接口。
//thread No.1 func1(){ std::unique_lock<mutex> lock(_mtx); //do something, now in here,and will leave this thread then mutex will unlock } //thread No.2 func2(){ std::unique_lock<mutex> lock(_mtx); //do something } //thread No.3 func3(){ std::unique_lock<mutex> lock(_mtx); //do something }
内容的提问来源于stack exchange,提问作者Yacheng Liu
相关产品推荐
相关产品推荐

