线程是现代计算机编程中的重要组件,它可以帮助程序在多个不同的任务之间交替执行。然而,线程的运行可能是异步的,这意味着它们可能会在程序的其他部分继续执行时继续运行,这可能会导致一些问题。其中最常见的问题是需要在主线程等待所有其他线程完成其工作后才能继续执行。
在这篇文章中,我们将探讨几种不同的方法来等待线程结束。这些方法包括 join, condition variables, futures 和 promises。
1. join
join 是最简单的等待线程结束的方法之一。该方法在执行完线程后阻止主线程继续执行,直到线程结束为止。下面是一个示例:
```
std::thread myThread(myFunction);
myThread.join();
```
在这个例子中,执行 myThread 的主线程将在 join 方法的调用后立即阻塞,直到 myThread 中调用的函数 myFunction 已完成。
2. condition variables
简而言之,条件变量是一种线程同步机制,允许线程等待某个条件变为真。
当一个线程需要等待某个条件时,它会调用条件变量的 wait 方法,等待其他线程发出通知,表示该条件已经满足。下面是一个带有条件变量的示例:
```
#include
#include
#include
std::mutex myMutex;
std::condition_variable myCondition;
std::queue
void producer() {
for (int i = 0; i < 10; ++i) {
std::unique_lock
myQueue.push(i);
myCondition.notify_one();
}
}
void consumer() {
while (true) {
std::unique_lock
myCondition.wait(lock, [] { return !myQueue.empty(); });
int value = myQueue.front();
myQueue.pop();
if (value == 9) {
break;
}
}
}
```
在这个示例中,producer 和 consumer 两个函数在不同的线程中运行。producer 生产一些数字,然后将它们推到队列中,并发出条件变量的通知,表示该队列非空。consumer 等待该队列变为非空,然后弹出数字,直到它弹出值为 9 的数字为止。
3. futures
future 是另一种等待线程结束的方法。这种方法允许一个线程安排一段代码在另一个线程中异步运行,并且在完成时,获取该代码的返回值。下面是示例:
```
#include
#include
int myFunction() {
return 42;
}
int main() {
std::future
std::cout << myFuture.get();
}
```
在这个示例中,我们对 myFunction 异步地进行调用。该方法将立即返回,而不会等待 myFunction 完成。然后,我们在 myFuture 中获取该函数的返回值并打印它。
4. promises
promise 是另一种等待线程结束的方法。这种方法允许一个线程异步地执行一些代码,并使用 promise 对象设置一个值。另一个线程可以使用该值,并且在该值被设置时阻塞。下面是示例:
```
#include
#include
void myFunction(std::promise
myPromise.set_value(42);
}
int main() {
std::promise
std::future
std::thread myThread(myFunction, std::move(myPromise));
std::cout << myFuture.get();
myThread.join();
}
```
在这个示例中,我们创建了一个 promise 和一个 future。然后,我们将 promise 传递给我的函数,并异步地运行该函数。当 myFunction 设置该 promise 的值时,future 将被解锁并打印出该值。最后,我们在线程上调用 join 方法,以等待线程完成。
我们已经看到了四种不同的方法来等待线程结束。join 是最简单且易于使用的方法,但它不能解锁其他线程同时运行。条件变量可以更好地解决此问题,但需要您进行更多的编码工作。futures 允许您异步地运行代码并获取结果,而 promises 则允许您设置值并在其他线程中获取该值。
扫码咨询 领取资料