gpt4 book ai didi

c++ - 主线程是否在阻塞线程上运行?

转载 作者:行者123 更新时间:2023-11-30 05:15:23 30 4
gpt4 key购买 nike

当我开始研究 c++11 中的线程时,我认为 .join() 用于在主线程和 std::async( ) 用于运行非阻塞线程。

在我看来,这个答案很好地解释了 std:async()https://stackoverflow.com/a/15035157/1770034

但我想更好地理解 join 方法。我发现了几个这样的例子: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() 完成,循环如何运行以加入更多线程?它的效果很棒!但是,为什么它会起作用?

为什么会这样?这是我对它的工作原理的印象。

  1. 主线程加入第一个线程。
  2. 主线程等待第一个线程完成。
  3. 第一个线程完成。
  4. 主线程继续for循环并加入第二个线程。
  5. 主线程等待第二个线程完成。
  6. ………………

如果它一直在 for 循环中循环,什么时候主线程实际上会被阻塞等待?

编辑

例子:

//Join the threads with the main thread
for (int i = 0; i < num_threads; ++i) {
t[i].join();
// --- Perform some long operation here ---
}

长操作什么时候发生?

最佳答案

当我发布这个问题时,我并没有完全理解多线程是怎么回事。

即使阅读了一些关于 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 个线程继续发生。现在我们加入 线程 10。它仍在运行,主线程现在将等待线程 10 完成。 (如果您需要在某个时间点完成代码才能继续前进,这很好。)

接下来我们有 return 0; 并且我们创建的 std::thread 超出范围,因为它们是对象,所以调用了析构函数。由于所有线程都连接到主线程,因此不会抛出任何异常,一切都会顺利结束。

如果我们想,“嘿,我不在乎线程是否完成,这个程序就结束了。”当 std::thread 析构函数被调用时,std::thread 对象会注意到有问题并引发 std::terminate

如果我们真的不关心线程什么时候结束或者它是否结束。我们可以使用分离。这将允许它运行,直到它完成它的任务。如果它仍在 main 的末尾运行,则线程将无一异常(exception)地终止(现代操作系统将随进程一起终止它。)

什么是joinablejoinable 如果您没有join 线程或detach 调用者(在我们的例子中是主线程)的线程,则为真。如果你想检查一个线程是否仍在运行而不是 join 它直到它是。您需要改用 std::async。 ( Can C++11 tell if std::thread is active? )

关于c++ - 主线程是否在阻塞线程上运行?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43118107/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com