41

我打算在主线程中触发 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确实让主线程等待子线程,但问题是,直到第一个线程完成后才会创建第二个线程。这不是我想要的。

我想要的是,在主线程中立即创建 2 个线程,然后主线程等待它们完成。似乎pthread_join无法做到这一点,可以吗?

我想,也许通过一个semaphore我可以完成这项工作,但还有其他方式吗?

4

4 回答 4

74
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;
}
于 2012-07-24T05:17:57.363 回答
17

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

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_attr_t变量,使用pthread_attr_init(3)然后pthread_attr_setdetachedstate(3) ,然后将其地址传递给pthread_create(3)第二个参数。Thos 将创建处于分离状态的线程。或者pthread_detach按照Jxh 的回答中的说明使用。

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

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

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

考虑一些面向代理的编程方法:根据经验,您不希望有很多线程(例如,10 核处理器上的 20 个线程是合理的,除非很多线程都在睡觉,否则 200 个线程不会是或等待)并且确实希望线程使用互斥锁和条件变量进行同步,并经常与其他线程通信和/或同步(每秒几次)。另请参阅poll(2)fifo(7)unix(7)sem_overview(7)shm_overview(7)作为线程之间通信的另一种方式。一般来说,避免在线程中使用信号(7)(阅读信号安全(7)...),并谨慎使用dlopen(3) (可能仅在主线程中)。

一种实用的方法是让你的大部分线程运行一些事件循环(使用poll(2)pselect(2),也许eventfd(2)signalfd(2),......),也许使用pipe(7 )unix(7)套接字。另请参见socket(7)

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

于 2012-07-24T05:20:02.877 回答
4

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

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);
}
于 2012-07-24T06:54:26.097 回答
0
#include<stdio.h>
#include<pthread.h>

int icnt = 0;   //in non_bss data segment
pthread_mutex_t lock;     //lock variable created stored into bss data segment


void *Thread_count(void* args)      //syncronization 
{
pthread_mutex_lock(&lock);              //lock aquire 
    
icnt++;

for(int x = 1; x <= icnt; x++)
{
    printf("Hello from Thread_count : %d \n",icnt);
}
printf("\n");

pthread_mutex_unlock(&lock);            //release lock  
pthread_exit(NULL);                     //exit from child thread
}


int main()
{

pthread_t threads[4];  //created array of {unsigned long int}
int status = 0;

//creating threads in loop      
for(int i = 1; i <= sizeof(threads)/sizeof(threads[0]); i++)
{
    pthread_create(&threads[i], NULL, &Thread_count, NULL);
}

//waiting for threads in loop
for(int j = 1; j <= sizeof(threads)/sizeof(threads[0]); j++)
{
    pthread_join(threads[j], &status);
    
    printf("Thread number : %d     <-->  Thread status : %d\n",j, status);
}


pthread_exit(0);  //end of main thread
}
于 2020-10-16T17:05:01.537 回答