在 c 中将多个线程加入一个线程

问题描述 投票:0回答:1

基本上主线程创建了 4 个线程 1 ,2 ,3 ,4 和 1、2、3 必须等待 4 结束,而 main 等待线程 1 2 3。 代码如下:

#include<stdio.h>
#include<pthread.h>
#include<stdlib.h>
#include<unistd.h>
pthread_t id[4];
void *func1(void *arg)
{
    printf("i am the %ith thread\n",(int)arg);
    pthread_join(id[3],NULL);
    printf("end of %ith thread\n",(int)arg);
    pthread_exit(NULL);
}
void *func2(void *arg)
{
    printf("i am the 4th thread\n");
    sleep(5);
    printf("end of 4th thread\n");
    pthread_exit(NULL);
}
int main()
{
    printf("start of main thread\n");
    pthread_create(&id[3],NULL,func2,NULL);
    for(int i=0;i<3;i++)
    {
        pthread_create(&id[i],NULL,func1,(void *)i);
    }
    for(int i=0;i<3;i++)
    {
        pthread_join(id[i],NULL);
    }
    printf("end of main\n");
    return 0;  
}

跑步时我得到这样的东西:` 主线程开始 我是第0个线程 我是第 4 个线程 我是第二个线程 我是第一个线程 4线程结束 第0个线程结束

请原谅这些可怕的信息,因为我匆忙将它们从法语翻译过来。 理论上线程 1 2 3 应该等待 4 然后自己完成,但每次尝试只有一个线程在 4 之后完成,然后整个执行被无限期地阻塞。 我尝试确保第 4 个线程总是首先从 pthread_attr_t 开始,并设置第 4 个高的调度优先级,但不幸的是,这没有用。 我尝试查找有关 pthread_join 的一些详细信息,如果将多个线程加入一个线程是不安全的或不允许的,但我没有找到任何建议。 任何帮助将不胜感激提前谢谢你。

c multithreading pthreads pthread-join
1个回答
0
投票

来自

pthread_join()
手册页:

如果多个线程同时尝试加入同一个线程,结果是不确定的。

如果需要在多个线程中等待线程终止,创建相应的标志包装到条件变量。在退出之前终止线程或在另一个线程中加入线程后广播条件变量。

补充说明:

  • 始终检查系统函数的返回值。
  • pthread_exit(NULL)
    在线程函数的末尾是多余的。只需返回 NULL。
  • int
    void*
    的转换可能会溢出,编译器不喜欢这样。我们可以使用
    intptr_t
    代替
    int
    但是在
    intptr_t
    中没有
    printf()
    的转换说明符,因此我们无论如何都应该转换。我们可以使用
    intptr_t
    的中间转换来让编译器开心。

程序可能是这样的:

#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>

static pthread_t id[4];

static pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
static int terminated = 0;

static void *func1(void *arg)
{
    printf("i am the %ith thread\n",(int)(intptr_t)arg);

    // Wait until 4th thread termination flag is set
    pthread_mutex_lock(&mtx);
    while (!terminated) {
        pthread_cond_wait(&cond, &mtx);
    }
    pthread_mutex_unlock(&mtx);

    printf("end of %ith thread\n",(int)(intptr_t)arg);
    return NULL;
}

static void *func2(void *)
{
    printf("i am the 4th thread\n");
    sleep(5);
    printf("end of 4th thread\n");

    // Set termination flag and broadcast state change
    pthread_mutex_lock(&mtx);
    terminated = 1;
    pthread_mutex_unlock(&mtx);
    pthread_cond_broadcast(&cond);

    return NULL;
}

int main()
{
    printf("start of main thread\n");
    int ret;

    ret = pthread_create(&id[3],NULL,func2,NULL);
    if (ret) {
        fprintf(stderr, "pthread_create(id[3]): %s\n", strerror(ret));
        return 1;
    }

    for(int i=0;i<3;i++)
    {
        ret = pthread_create(&id[i],NULL,func1,(void *)(intptr_t)i);
        if (ret) {
            fprintf(stderr, "pthread_create(id[%i]): %s\n", i, strerror(ret));
            return 1;
        }
    }

    // Wait for all 4 threads
    for(int i=0;i<4;i++)
    {
        int ret = pthread_join(id[i],NULL);
        if (ret != 0) {
            fprintf(stderr, "pthread_join(id[%i]): %s\n", i, strerror(ret));
        }
    }

    printf("end of main\n");
    return 0;  
}

UPD:有更简单的方法:将

pthread_join()
调用包装到由互斥锁保护的临界区:

static pthread_t id[4];

static pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;
static int terminated = 0;

static void *func1(void *arg)
{
    printf("i am the %ith thread\n",(int)(intptr_t)arg);

    // Wait until 4th thread termination flag is set
    pthread_mutex_lock(&mtx);
    if (!terminated) {
        int ret = pthread_join(id[3],NULL);
        if (ret != 0) {
            fprintf(stderr, "pthread_join(id[3]): %s\n", strerror(ret));
        }
        terminated = 1;
    }
    pthread_mutex_unlock(&mtx);

    printf("end of %ith thread\n",(int)(intptr_t)arg);
    return NULL;
}

static void *func2(void *)
{
    printf("i am the 4th thread\n");
    sleep(5);
    printf("end of 4th thread\n");

    return NULL;
}

在这种情况下,您不需要在

main()
中加入第4个线程:

    for(int i=0;i<3;i++) {
        int ret = pthread_join(id[i],NULL);
    ...
© www.soinside.com 2019 - 2024. All rights reserved.