当前位置: 首页 > 知识库问答 >
问题:

如何让主线程等待所有子线程完成?

王才英
2023-03-14

我打算在主线程中启动2个线程,主线程应该等到所有2个子线程完成,我就是这样做的。

void *routine(void *arg)
{
    sleep(3);
}

int main()
{
    for (int i = 0; i < 2; i++) {
        pthread_t tid;
        pthread_create(&tid, NULL, routine, NULL);
        pthread_join(&tid, NULL);  //This function will block main thread, right?
    }
}

在上面的代码中,pthread_join确实让主线程等待子线程,但问题是,在第一个线程完成之前不会创建第二个线程。这不是我想要的。

我想要的是,这两个线程立即在主线程中创建,然后主线程等待它们完成。似乎pthread_join做不到,是吗?

我想,也许我可以通过一个信号灯来完成这项工作,但还有别的方法吗?

共有3个答案

蓬英逸
2023-03-14

您可以分离启动线程,而不必担心加入。

for (int i = 0; i < 2; i++) {
    pthread_t tid;
    pthread_create(&tid, NULL, routine, NULL);
    pthread_detach(tid);
}
pthread_exit(0);

或者,您可以让死亡的线程向主线程报告它是谁,以便线程按照它们退出的顺序连接,而不是按照您创建它们的顺序连接。

void *routine(void *arg)
{
    int *fds = (int *)arg;
    pthread_t t = pthread_self();
    usleep((rand()/(1.0 + RAND_MAX)) * 1000000);
    write(fds[1], &t, sizeof(t));
}

int main()
{
    int fds[2];
    srand(time(0));
    pipe(fds);
    for (int i = 0; i < 2; i++) {
        pthread_t tid;
        pthread_create(&tid, NULL, routine, fds);
        printf("created: %llu\n", (unsigned long long)tid);
    }
    for (int i = 0; i < 2; i++) {
        pthread_t tid;
        read(fds[0], &tid, sizeof(tid));
        printf("joining: %llu\n", (unsigned long long)tid);
        pthread_join(tid, 0);
    }
    pthread_exit(0);
}
长孙弘壮
2023-03-14

首先创建所有线程,然后加入所有线程:

pthread_t tid[2];

/// create all threads
for (int i = 0; i < 2; i++) {
    pthread_create(&tid[i], NULL, routine, NULL);
}

/// wait all threads by joining them
for (int i = 0; i < 2; i++) {
    pthread_join(tid[i], NULL);  
}

或者,使用一些pthread\u attr\u t变量,在其上使用pthread\u attr\u init(3),然后使用pthread\u attr\u setdetachedstate(3),然后将其地址传递给pthread\u create(3)第二个参数。Thos将在分离状态下创建线程。或者使用Jxh的答案中解释的pthread\u detach。

记得阅读一些好的Pthread教程。您可能希望使用互斥锁和条件变量。

您可以使用包装它们的框架,例如Qt或POCO(在C中),或者阅读一本好的C书籍并使用C线程。

从概念上讲,线程都有自己的调用堆栈,并且与延续相关。它们很“重”。

考虑一些面向代理的编程方法:根据经验,你不希望有很多线程(例如,10核处理器上有20个线程是合理的,除非有很多线程处于睡眠或等待状态,否则200个线程是不合理的),并且确实希望线程使用互斥锁和条件变量进行同步,并经常与其他线程通信和/或同步(每秒数次)。另请参阅轮询(2)、fifo(7)、unix(7)、sem_概述(7)和shm_概述(7),作为线程之间通信的另一种方式。一般情况下,避免使用带线程的信号(7)(读取信号安全(7)…),并小心使用dlopen(3)(可能仅在主线程中)。

一种实用的方法是让大多数线程运行一些事件循环(使用poll(2)、pselect(2)、可能是eventfd(2)、signalfd(2)、…),可能使用管道(7)或unix(7)套接字进行通信。另见插座(7)。

不要忘记(在纸上)记录线程之间的通信协议。对于理论方法,请阅读有关π演算的书籍并了解Rice定理:调试并发程序是困难的。

邹举
2023-03-14
int main()
{
    pthread_t tid[2];
    for (int i = 0; i < 2; i++) {
        pthread_create(&tid[i], NULL, routine, NULL);
    }
    for (int i = 0; i < 2; i++)
       pthread_join(tid[i], NULL);
    return 0;
}
 类似资料:
  • 在下面的Haskell代码中,如何强制主线程等待其所有子线程完成。 我无法使用forkFinal,因为在“终止程序”一节中给出了这个链接:(http://hackage.haskell.org/package/base-4.7.0.2/docs/Control-Concurrent.html)。 当使用TMVar时,我得到了想要的结果。但是我想用TVar做这件事。请帮忙。

  • 有时我看到一些线程还没有完成他们的工作,服务杀死那个线程,我怎么能强迫服务等待,直到线程完成他们的工作? 这是我的代码: 我看到了一些例外。future.is完成())块。我怎么能确保每一个未来是当执行者服务关闭?

  • 我想在C#中处理子目录和文件的文件系统/文件夹。我正在使用TPL库中的任务。这个想法是递归地执行它并为每个文件夹创建一个任务。主线程应该等待子线程完成,然后打印一些信息。事实上我只是想知道扫描何时完成。我已经开始使用线程池,然后切换到TLP。做了一些简单的例子。经过一些尝试从简单的代码到越来越臃肿的代码我被困在这里: 主线程有时仍然过早地继续,而不是在完成所有其他线程之后继续。(我对C#比较陌生,

  • 这可能是在类似的背景下问的,但我在搜索了大约20分钟后找不到答案,所以我会问。 我已经编写了一个Python脚本(比如说:scriptA.py)和一个脚本(比如说scriptB.py) 在scriptB中,我想用不同的参数多次调用scriptA,每次运行大约需要一个小时,(这是一个巨大的脚本,做了很多事情……不用担心),我希望能够同时使用所有不同的参数运行scriptA,但我需要等到所有参数都完成

  • 问题内容: 我需要一次执行一些任务4,如下所示: 全部完成后如何获得通知?现在,我想不出什么比设置一些全局任务计数器并在每个任务结束时减少它,然后无限循环监视此计数器为0更好的了。或获取期货的列表,并在无限循环中对所有期货进行isDone监视。什么是不涉及无限循环的更好的解决方案? 问题答案: 基本上在你致电之后:

  • 问题内容: 问题描述 : - 步骤1: 在主线程中从用户那里获取输入FILE_NAME。 步骤2: 对该文件执行10个操作(即,计数字符,计数行等。),所有这10个操作必须位于单独的线程中。这意味着必须有10个子线程。 步骤3: 主线程等待,直到所有那些子线程完成。 步骤4: 打印结果。 我做了什么 :- 我用3个线程做了一个示例代码。 我不希望您遇到文件操作代码。 问题:- 我上面的代码没有给出