C-大量posix线程失控,不再创建新线程

C-大量posix线程失控,不再创建新线程,c,macos,posix,pthreads,C,Macos,Posix,Pthreads,我在类中有一个赋值要求我们使用POSIX线程并创建其中的n*(n-1)/2个线程来处理一个包含n个元素的数据集 你可以把它看作是概率上的经典“握手” 我知道,对于大型数据集,它将使应用程序CPU受限,最终它将花费大量时间切换上下文,这将是无用的,但任务要求我们这样做 但是,我创建所有线程的循环在一段时间后停止创建它们 对于下面的代码,我将看到如下输出: making thread thread start thread done made thread 1944 making thread th

我在类中有一个赋值要求我们使用POSIX线程并创建其中的n*(n-1)/2个线程来处理一个包含n个元素的数据集

你可以把它看作是概率上的经典“握手”

我知道,对于大型数据集,它将使应用程序CPU受限,最终它将花费大量时间切换上下文,这将是无用的,但任务要求我们这样做

但是,我创建所有线程的循环在一段时间后停止创建它们

对于下面的代码,我将看到如下输出:

making thread
thread start
thread done
made thread 1944
making thread
thread start
thread done
made thread 1945
making thread
thread start
thread done
made thread 1946
making thread
有一段时间,但之后我将不再看到“线程开始”和“线程完成”消息,而只看到“生成线程,生成线程”消息

以下是创建线程的循环:

    int tCtr = 0;
    tArr = (pthread_t*)malloc(((numbers_read) * (numbers_read - 1)/2) * sizeof(pthread_t));
    for(i=0; i<numbers_read; i++){
        int j;
        for(j=i; j<numbers_read; j++){
            // n(n-1)/2
            if(i != j){
                printf("making thread\n");
                struct comparison_struct *data;
                data = (struct comparison_struct *)malloc(sizeof(struct comparison_struct));
                data->i_value = &numbers[i];
                data->j_value = &numbers[j];
                data->i_arr_entry = &wArr[i];
                data->j_arr_entry = &wArr[j];
                pthread_create(&tArr[tCtr], NULL, compare_thread, (void *)data);
                printf("made thread %d\n", tCtr);
                tCtr++;
            }
        }
    }
    for(i=0; i<tCtr; i++){
        pthread_join(tArr[i], NULL);
    }
    free(tArr);
inttctr=0;
tArr=(pthread_t*)malloc((numbers_read)*(numbers_read-1)/2)*sizeof(pthread_t));
对于(i=0;ij_值=&numbers[j];
数据->i_arr_entry=&wArr[i];
数据->j_arr_entry=&wArr[j];
pthread_创建(&tArr[tCtr],NULL,比较_线程,(void*)数据);
printf(“制成螺纹%d\n”,tCtr);
tCtr++;
}
}
}
对于(i=0;ii_值j_值){
*数据->i_arr_entry=0;
}否则{
*数据->j_arr_条目=0;
}
免费(vData);
printf(“线程完成\n”);
返回NULL;
}
有人有什么想法吗?我是pthreads新手,很难理解


我知道,如果我在创建pthread_之后立即调用pthread_join,应用程序就会工作——但是它会在每个线程上阻塞,我认为这会降低性能,因为一次实际上只有两个线程在运行。

检查pthread_create的返回值,可能您达到了资源限制

 pthread_create() will fail if:

 [EAGAIN]           The system lacked the necessary resources to create
                    another thread, or the system-imposed limit on the
                    total number of threads in a process
                    [PTHREAD_THREADS_MAX] would be exceeded.

 [EINVAL]           The value specified by attr is invalid.

如果达到资源限制,您可以尝试创建一个与其他线程连接的线程,创建一个工作线程队列,并通过队列为每个线程分配工作,或者如果您控制系统的资源限制,请尝试增加它。

检查pthread\u create的返回值,可能您达到了资源限制

 pthread_create() will fail if:

 [EAGAIN]           The system lacked the necessary resources to create
                    another thread, or the system-imposed limit on the
                    total number of threads in a process
                    [PTHREAD_THREADS_MAX] would be exceeded.

 [EINVAL]           The value specified by attr is invalid.
如果达到资源限制,可以尝试创建一个与其他线程连接的线程,创建一个工作线程队列,并通过该队列为每个线程分配工作,或者如果控制系统的资源限制,则可以尝试增加它

如果我在pthread_创建之后立即调用
pthread_join
,那么它会在每个线程上阻塞…实际上一次只有两个线程在运行

加入线程的另一种方法是只将它们创建为已分离。创建并初始化
pthread\u attr\t,
将其设置为已分离,并使用
pthread\u create
调用传递attr

pthread_attr_t  attr;
int             ret;

ret = pthread_attr_init(&attr);
if (ret)
   // error .........

ret = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);

for (....)
{
    //........
    ret = pthread_create(&tArr[tCtr], &attr, compare_thread, (void *)data);
    //.......
}

ret = pthread_attr_destroy(&attr);
也不要求创建另一个线程的线程必须是加入它的线程。您可以创建一个线程来加入所有其他创建的线程。但这可能超出了此任务的职责范围

如果我在pthread_创建之后立即调用
pthread_join
,那么它会在每个线程上阻塞…实际上一次只有两个线程在运行

加入线程的另一种方法是只将它们创建为已分离。创建并初始化
pthread\u attr\t,
将其设置为已分离,并使用
pthread\u create
调用传递attr

pthread_attr_t  attr;
int             ret;

ret = pthread_attr_init(&attr);
if (ret)
   // error .........

ret = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);

for (....)
{
    //........
    ret = pthread_create(&tArr[tCtr], &attr, compare_thread, (void *)data);
    //.......
}

ret = pthread_attr_destroy(&attr);

也不要求创建另一个线程的线程必须是连接它的线程。您可以创建一个线程来连接所有其他创建的线程。但这可能超出了此任务的职责范围。

或者要解决米老鼠问题,请稍微展开循环,以便创建几个t线程,然后连接所有线程,然后再创建几个线程,依此类推。任务可能会说您必须创建所有这些线程,但它是说您必须让它们同时运行吗?;-)或者要解决米老鼠问题,请稍微展开循环,以便创建几个线程,然后连接所有线程,然后再多创造一些,以此类推。作业可能会说您必须创建所有这些线程,但它是否说您必须让它们同时运行?;-)我不会太担心性能,除非它是任务的一部分,或者程序需要永远运行。性能的限制因素是创建和破坏线程的喷射。无论线程做了多少并行工作,这里的大部分工作都是在主线程中完成的。这不是一个非常现实的优化场景,因为在几乎所有的情况下,这是你的瓶颈,你会减少线程的数量,给每个线程更多的工作。登录后,真正的瓶颈可能是终端,其他一切都可以忽略不计。我不会太担心性能,除非它是任务的一部分,或者程序需要永远运行。性能的限制因素是创建和破坏线程的喷射。无论线程做了多少并行工作,这里的大部分工作都是在主线程中完成的。这不是一个非常现实的优化场景,因为在几乎所有的情况下,这是你的瓶颈,你会减少线程的数量,给每个线程更多的工作。登录后,真正的瓶颈可能是终端,其他一切都可以忽略不计。