当我开始研究c ++ 11中的线程时,我认为.join()
用于在主线程上进行阻塞操作,而std::async()
用于运行非阻塞线程。
这个答案在我看来很好地解释了std:async()
。 https://stackoverflow.com/a/15035157/1770034
但我想更好地理解连接方法。我发现了几个这样的例子:https://stackoverflow.com/a/11229853/1770034其中只有1个线程是从主线程创建的。
然后我发现了这个https://solarianprogrammer.com/2011/12/16/cpp-11-thread-tutorial/
网站代码片段:
#include <iostream>
#include <thread>
static const int num_threads = 10;
//This function will be called from a thread
void call_from_thread(int tid) {
std::cout << "Launched by thread " << tid << std::endl;
}
int main() {
std::thread t[num_threads];
//Launch a group of threads
for (int i = 0; i < num_threads; ++i) {
t[i] = std::thread(call_from_thread, i);
}
std::cout << "Launched from the main\n";
//Join the threads with the main thread
for (int i = 0; i < num_threads; ++i) {
t[i].join();
}
return 0;
}
我对此部分感到好奇的部分就在这里:
//Join the threads with the main thread
for (int i = 0; i < num_threads; ++i) {
t[i].join();
}
如果主线程停止等到.join()
完成,那么循环如何运行以加入更多线程?它的工作原理很棒!但是,它为什么有用?
为什么这样工作?这是我对它如何运作的印象。
如果主线程实际上被阻止等待,它是否继续循环执行for循环?
修改
示例:
//Join the threads with the main thread
for (int i = 0; i < num_threads; ++i) {
t[i].join();
// --- Perform some long operation here ---
}
什么时候会进行长时间的操作?
答案 0 :(得分:1)
当我发布这个问题时,我并不完全了解多线程的确切情况。
即使在阅读有关C ++主题的几篇教程中,它仍然有点模糊不清。所以这是对实际情况的解释。
为了简单起见,让我们使用这段代码:
#include <thread>
void my_function()
{
*** Some Code ***
}
int main()
{
std::thread threads[10]; //create 10 std::thread objects
for(int loop = 0; loop < 10; loop++)
{
threads[loop] = std::thread(my_function);
}
//Threads are executing on machine and main code is also running
for(int loop = 0; loop < 10; loop++)
{
threads[loop].join; //If threads[loop] is still running wait for it, otherwise keep moving forward.
}
return 0;
} //all 10 thread objects (threads) are going out of scope and their destructors are being called
在main的顶部(在主线程中),我们为堆栈上的10个线程对象创建空间。在第一个for循环中,我们实际创建了一个std::thread
,它将在一个单独的线程上调用my_function
。
假设我们有一个四核处理器,一个线程一次只能在一个处理器上运行。 (相当假设!)主线程当前正在使用其中一个处理器,我们的10个线程中的一个将使用第二个。剩下的9个中的一个将使用第三个,其余8个中的一个将使用第四个。
在for
循环之间,我们可以在主线程上执行我们想要的所有代码。 (即:主线程未被阻止)。接下来我们进入第二个for
循环。这个循环将通过并告诉每个线程join
。
让我们假设线程1-9已经在这个时间点执行,但我们仍然在后台运行线程10。当for
循环加入线程1.由于它已经完成,for
循环再次运行。这通过前9个线程继续发生。现在我们join
线程10.它仍然在运行,主线程现在将等待线程10完成。 (如果您需要在某个时间点完成代码才能继续前进,这很好。)
接下来我们有return 0;
和我们创建的std::thread
超出范围,因为它们是对象,所以调用析构函数。由于所有线程都连接到main,因此不会抛出任何异常,并且一切都很好地结束。
如果我们想,“嘿,我不在乎线程是否完成,这个程序结束了。”调用std::thread
析构函数时,std::thread
对象会发现错误并引发std::terminate
。
如果我们真的不关心线程何时完成或完成。我们可以使用detach
。这将允许它运行直到完成任务。如果它仍然在main的末尾运行,则线程将毫无例外地死亡(现代操作系统将使用该进程终止它。)
什么是joinable
?如果你没有joinable
来自调用者的线程join
或detach
线程(在我们的例子中是主线程),那么join
将是真的。如果你想检查一个线程是否仍在运行而不是std::async
它,直到它为止。您需要使用v-on:input
代替。 (Can C++11 tell if std::thread is active?)