在C++中,如果你想要一个线程阻塞并等待其他线程或某种外部条件来“激活”它,通常有以下几种方法:
-
使用条件变量(Condition Variables):
条件变量是C++中用于线程同步的一种机制。一个线程可以在某个条件不满足时阻塞,并在其他线程改变了条件后继续执行。这通常与互斥锁(mutexes)一起使用,以确保条件的安全检查和更新。示例:
#include <iostream> #include <thread> #include <mutex> #include <condition_variable> using namespace std; //阻塞线程,等待他人激活 std::mutex mtx; std::condition_variable cv; bool ready = false; void go() { //std::unique_lock<std::mutex> lck(mtx); ready = true; // 设置条件变量 cv.notify_all(); // 唤醒所有等待的线程 } void print_id(int id) { std::unique_lock<std::mutex> lck(mtx); while (true) { // 等待条件满足 cout << " wait:"<<id<<"\n"; if (id == 9) { std::cout << "notify_all"<< '\n'; go(); } //lck.unlock(); cv.wait(lck); // 如果条件不满足,则线程阻塞 if (ready) { break; } } // ... 在此处执行线程任务 ... std::cout << "thread " << id << '\n'; } int main() { std::thread threads[10]; ready = true; for (int i = 0; i < 10; ++i) { threads[i] = std::thread(print_id, i); } std::cout << "10 threads ready to race...\n"; for (auto& th : threads) { th.join(); } go(); // 激活线程 for (auto& th : threads) { //th.join(); } return 0; }
10 threads ready to race...
wait:1
wait:0
wait:2
wait:3
wait:4
wait:5
wait:6
wait:7
wait:8
wait:9
notify_all
thread 1
thread 6
thread 3
thread 4
thread 7
thread 5
thread 8
thread 2
thread 0 -
使用
std::future
和std::promise
:
你可以使用std::promise
和std::future
来传递一个值或异常给另一个线程。一个线程可以设置std::promise
的值或异常,而另一个线程可以获取std::future
的值或异常。这可以用于实现线程之间的阻塞等待。示例:
#include <iostream> #include <thread> #include <future> void async_task(std::promise<void> prom) { // ... 执行一些任务 ... std::cout << "Task done, notifying...\n"; prom.set_value(); // 设置值,唤醒等待的线程 } int main() { std::promise<void> prom; std::future<void> fut = prom.get_future(); std::thread th(async_task, std::move(prom)); fut.wait(); // 阻塞等待,直到另一个线程设置值 std::cout << "Main thread notified\n"; th.join(); return 0; }
Task done, notifying...
Main thread notified -
使用
std::this_thread::yield
:
虽然std::this_thread::yield
并不直接让线程阻塞等待其他线程激活,但它可以让当前线程放弃对CPU的占用,以便其他线程可以获得执行机会。这通常用于编写响应式多线程程序,但并不能实现阻塞等待。 -
使用第三方库:
还有一些第三方库提供了更高级的线程同步和阻塞机制,如Boost库等。
在所有这些情况下,你都应该仔细考虑线程安全性和性能问题,确保你的程序能够正确地处理并发和同步问题。