是否可以在没有 pthread_join() 的情况下使用 pthread?

Posted

技术标签:

【中文标题】是否可以在没有 pthread_join() 的情况下使用 pthread?【英文标题】:Is it possible to use pthreads without pthread_join()? 【发布时间】:2011-06-21 22:10:06 【问题描述】:

我最近在尝试将一些多线程功能添加到我的一些代码中以用于工作项目时注意到的是,pthread 在后勤处理方面是一个巨大的痛苦......

这是场景...

我的主方法(服务器)中有一个无限循环,只要它从任何客户端接收到数据包,就会产生线程来处理数据。问题是我根本无法让线程同时执行。他们拒绝开始执行,直到从 main 方法调用 pthread_join() ,这完全破坏了首先使用线程的全部目的(服务器需要停止执行流程,并等待线程在接收之前完成处理其数据不再有数据包!荒谬。)

那么有没有办法使用 pthread 并让它们实际上是多线程的?还是我最好完全不使用线程,并通过在我的服务器中停止执行来调用函数来处理数据来节省额外的资源?

我在想我可能每次都不得不求助于分叉......

这令人沮丧....

我做的一些示例代码如下:

// gcc threads.c -lpthread
#include <stdio.h>
#include <pthread.h>

struct point
    int x, y;
;

static void *print_point(void *point_p);

int main() 
    pthread_t tid;
    struct point pt = 3, 5;
    printf("enter main\n");
    pthread_create(&tid, NULL, print_point, &pt);
    while(1)continue;
    return 0;


static void *print_point(void *point_p) 
    struct point arg = * (struct point *) point_p;
    printf("Point: (%d, %d)\n", arg.x, arg.y);
    return NULL;

当我运行并编译它时(是的,我使用 -lpthread 开关编译),它打印“进入 main”并且不执行线程......我什至让它运行了一段时间(起床,去上厕所,吃了点东西),还是什么都没有。

所以由于 main 方法产生一个线程然后无限循环,线程最终应该执行......对吗?从我的测试中可以看出,主方法永远不会放弃对它产生的线程的执行。我可以通过调用 join 让它放弃它的唯一方法(但这违背了拥有线程的目的,因为 main 会一直等到线程完成)。

【问题讨论】:

这对我来说很好。尽管在 main 函数中设置忙等待循环可能是不可取的;改用大号sleep 对于这个特定的示例,请确保刷新标准输出。否则,该短字符串将位于输出缓冲区中,但尚未打印到屏幕上,因为 I/O 系统在打印任何内容之前正在等待更多数据。不过,这不应该是您的服务器程序的问题。 @Rob:stdout 不会自动刷新到换行符吗? while(1)continue; 这样的紧密循环可能会导致调度问题。相反,使用sleep 来确保操作系统有机会重新安排。确保您在服务器应用程序中执行此操作,这可能是问题所在(尽管在您的服务器中您可能正在等待select 或其他东西?) +1 对 Oli 的评论:使用睡眠来强制上下文切换。使用 while(true) 循环无法保证您这样做。 【参考方案1】:

您永远不会让线程有机会使用 while(1)continue; 执行。这里会发生两件事之一。

    您已使用足够高的优化进行编译,编译器会使整个循环消失。线程永远没有机会执行,因为 main 启动线程然后立即返回零。 编译器不会优化循环。在这个繁忙的循环中,您再一次没有让线程机制有机会溜进去。

sleep (0); 调用添加到该繁忙循环的主体。

【讨论】:

编译器永远不会优化循环。 @Oli:见***.com/questions/3592557/…。 @David:多么奇怪的概念!我没有意识到这一点。【参考方案2】:

实际上,您的代码对我来说很好,但我认为您的问题是主线程位于 while() 循环中,占用了所有 CPU 使用率,因此第二个线程永远没有机会。 pthread_join 使它工作的事实有点像红鲱鱼:它只是停止主线程,以便其他线程有机会。

显然,正确的解决方法是让主线程在无事可做时正常休眠。对于您的测试代码,请尝试将 sleep(1) 放入您的 while 循环中。

【讨论】:

sleep(0) 也有效。一秒钟在狗年中是很长的时间,在 CPU 年中甚至更长。调用 sleep(0) 是让其他线程有机会占用 CPU 的标准技巧。 @Rob:注意它不是你需要的 sleep(0)。它让主线程暂停一秒钟(不要从字面上看那一秒钟),以便让其他线程有机会运行。 sleep(0) 只是一个简单的技巧来说明这一点。如果你在做一个真正的服务器,你会调用类似 select() 的东西,它会产生同样的效果。 @David:是的。我猜 pthread_yield() 是实现与 sleep(0) 相同的更明确的方式。 @Martin:这里的问题是 Rob 从未释放 CPU。我同意在实际应用程序中,在实际应用程序中需要 sleep() 以外的其他内容。例如,读取传入数据包的东西。我不想详细介绍如何使用select() 来做到这一点。 OTOH,调用 sleep(0) 是一种典型的技巧,用于让 CPU 绑定线程暂时放弃对 CPU 的控制。非标准的pthread_yield() 或标准的sched_yield() 有时有点过于严厉了。

以上是关于是否可以在没有 pthread_join() 的情况下使用 pthread?的主要内容,如果未能解决你的问题,请参考以下文章

pthread_join - 多个线程等待

windows 下有没有类似linux中的pthread_detach,pthread_join和pthread_joinable函数

使用一个参数调用 pthread_join 会导致分段错误?

如何停止在共享库中实现的阻塞 pthread_join()

SylixOS pthread_join退出

pthread_join / __pthread_internal_find 函数发生SIGABRT的crash (Android)