C++11中如何让新线程先于主线程获取std::mutex
如何确保线程t先于main线程获取互斥锁(C++11实现)
你碰到的这个问题确实很常见——直接用std::lock_guard的话,主线程很可能因为线程启动的延迟抢先拿到互斥锁,没法保证线程t先获取。下面我给你两种基于C++11标准的靠谱实现方式:
方案一:使用std::promise和std::future实现同步
这种方式通过线程间的"信号传递"让主线程等待线程t成功锁定互斥锁后,再尝试获取锁。代码示例如下:
#include <mutex> #include <thread> #include <future> std::mutex m; std::promise<void> t_locked_promise; void t() { std::lock_guard<std::mutex> lock(m); // 通知主线程:我已经拿到互斥锁了 t_locked_promise.set_value(); // 这里可以添加线程t持有锁时需要执行的逻辑 // ... } int main() { std::thread t_thread(t); // 等待线程t发出"已锁定互斥锁"的信号 t_locked_promise.get_future().wait(); // 此时线程t已经持有锁,主线程再尝试获取(会阻塞直到t释放) std::lock_guard<std::mutex> lock(m); // 主线程持有锁时的逻辑 // ... t_thread.join(); return 0; }
原理说明
- 线程t启动后,首先锁定互斥锁,然后通过
std::promise::set_value()向主线程的std::future发送信号。 - 主线程在创建线程后,立即调用
future.wait()阻塞,直到收到线程t的信号,才会尝试获取互斥锁。这就完全避免了主线程先抢到锁的可能。
方案二:使用std::condition_variable和标志位
这种方式通过条件变量让主线程等待线程t完成锁的获取,逻辑和promise类似,但更适合需要重复同步的场景:
#include <mutex> #include <thread> #include <condition_variable> std::mutex m; std::mutex cv_mutex; std::condition_variable t_locked_cv; bool t_has_locked = false; void t() { std::lock_guard<std::mutex> lock(m); // 标记线程t已锁定,并通知主线程 { std::lock_guard<std::mutex> cv_lock(cv_mutex); t_has_locked = true; } t_locked_cv.notify_one(); // 线程t持有锁的逻辑 // ... } int main() { std::thread t_thread(t); // 等待线程t的锁定通知 { std::unique_lock<std::mutex> cv_lock(cv_mutex); t_locked_cv.wait(cv_lock, []{ return t_has_locked; }); } // 主线程尝试获取锁 std::lock_guard<std::mutex> lock(m); // 主线程逻辑 // ... t_thread.join(); return 0; }
原理说明
- 线程t锁定互斥锁后,设置标志位
t_has_locked并通过条件变量通知主线程。 - 主线程通过
cv.wait()阻塞,直到标志位变为true(确保线程t已经拿到锁),之后才会去尝试获取互斥锁。
注意事项
- 两种方案的核心都是让主线程等待线程t完成锁的获取动作后,再尝试自己获取锁,从根本上消除了主线程先抢到锁的可能性。
- 如果你需要线程t持有锁期间执行的逻辑较长,主线程会在尝试获取锁时自然阻塞,直到t释放锁,这符合常规的互斥锁使用逻辑。
内容的提问来源于stack exchange,提问作者Nisba
相关产品推荐
相关产品推荐

