如何在 C 程序中终止线程

如何在 C 程序中终止线程

在Linux线程系列的第二部分(线程创建和识别)中,我们讨论了线程ID,如何比较两个线程ID以及如何创建线程。

在本文中,我们将主要关注线程是如何终止的。

C 线程示例程序

如果我们采用本系列第二部分中讨论的相同示例:

#include

#include

#include

#include

#include

pthread_t tid[2];

void* doSomeThing(void *arg)

{

unsigned long i = 0;

pthread_t id = pthread_self();

if(pthread_equal(id,tid[0]))

{

printf("\n First thread processing\n");

}

else

{

printf("\n Second thread processing\n");

}

for(i=0; i<(0xFFFFFFFF);i++);

return NULL;

}

int main(void)

{

int i = 0;

int err;

while(i < 2)

{

err = pthread_create(&(tid[i]), NULL, &doSomeThing, NULL);

if (err != 0)

printf("\ncan't create thread :[%s]", strerror(err));

else

printf("\n Thread created successfully\n");

i++;

}

sleep(5);

return 0;

}

您是否观察到正在使用的“sleep()”函数?您是否有关于为什么使用 sleep() 的问题?好吧,如果你这样做了,那么你就在正确的地方得到答案,如果你没有,那么它也将是一个很好的预读。

如果我从上面的代码中删除 sleep() 函数,然后尝试编译并运行它,我会看到以下输出:

$ ./threads

Thread created successfully

First thread processing

Thread created successfully

但是,如果我在启用 sleep() 的情况下运行它,那么我会看到输出为:

$ ./threads

Thread created successfully

First thread processing

Thread created successfully

Second thread processing

因此,如果我们删除 sleep() 函数,我们会看到日志“第二线程处理”丢失。

那么,为什么会发生这种情况?嗯,这是因为就在第二个线程即将被调度之前,父线程(从它创建了两个线程)完成了它的执行。这意味着运行 main() 函数的默认线程已完成,因此进程在 main() 返回时终止。

线程终止

正如上面已经讨论过的,每个程序都从至少一个线程开始,该线程是执行 main() 函数的线程。所以程序中执行的每个线程的最大生命周期就是主线程的生命周期。因此,如果我们希望主线程应该等到所有其他线程都完成,那么就有一个函数 pthread_join()。

#include

int pthread_join(pthread_t thread, void **rval_ptr);

上面的函数确保其父线程在完成之前不会终止。该函数在父线程中调用,第一个参数是要等待的线程的线程 ID,第二个参数是我们希望父线程等待的线程的返回值。如果我们对返回值不感兴趣,那么我们可以将此指针设置为 NULL。

如果我们在更广泛的层面上进行分类,那么我们会看到线程可以通过三种方式终止:

如果线程从其启动例程返回。

如果它被其他线程取消。这里使用的函数是 pthread_cancel()。

如果它从自身内部调用 pthread_exit() 函数。

这里的重点是 pthread_exit()。它的原型如下:

#include

void pthread_exit(void *rval_ptr);

所以我们看到这个函数只接受一个参数,就是调用这个函数的线程的返回值。该返回值由等待该线程终止的父线程访问。由 pthread_exit() 函数终止的线程的返回值可以在上面刚刚解释的 pthread_join 的第二个参数中访问。

C 线程终止示例

让我们举个例子,我们使用上面讨论的函数:

#include

#include

#include

#include

#include

pthread_t tid[2];

int ret1,ret2;

void* doSomeThing(void *arg)

{

unsigned long i = 0;

pthread_t id = pthread_self();

for(i=0; i<(0xFFFFFFFF);i++);

if(pthread_equal(id,tid[0]))

{

printf("\n First thread processing done\n");

ret1 = 100;

pthread_exit(&ret1);

}

else

{

printf("\n Second thread processing done\n");

ret2 = 200;

pthread_exit(&ret2);

}

return NULL;

}

int main(void)

{

int i = 0;

int err;

int *ptr[2];

while(i < 2)

{

err = pthread_create(&(tid[i]), NULL, &doSomeThing, NULL);

if (err != 0)

printf("\ncan't create thread :[%s]", strerror(err));

else

printf("\n Thread created successfully\n");

i++;

}

pthread_join(tid[0], (void**)&(ptr[0]));

pthread_join(tid[1], (void**)&(ptr[1]));

printf("\n return value from first thread is [%d]\n", *ptr[0]);

printf("\n return value from second thread is [%d]\n", *ptr[1]);

return 0;

}

在上面的代码中:

我们使用 pthread_create() 创建了两个线程

两个线程的启动函数相同,即 doSomeThing()

线程使用带有返回值的 pthread_exit() 函数从 start 函数中退出。

在线程创建后的main函数中,调用pthread_join()函数等待两个线程完成。

一旦两个线程都完成,它们的返回值将由 pthread_join() 调用中的第二个参数访问。

上述代码的输出如下:

$ ./threads

Thread created successfully

Thread created successfully

First thread processing done

Second thread processing done

return value from first thread is [100]

return value from second thread is [200]

所以我们看到两个线程都完全执行,并且在主函数中访问了它们的返回值。

相关推荐

合作伙伴