0


Linux线程 | 创建 终止 回收 分离

一、线程简介

图片1

  • 线程是参与系统调度的最小单位。它被包含在进程之中,是进程中的实际运行单位。
  • 一个进程中可以创建多个线程,多个线程实现并发运行,每个线程执行不同的任务。
  • 每个线程都有其对应的标识,称为线程 ID,线程 ID 使用 pthread_t 数据类型来表示。

二、线程的创建

线程是轻量级的并发执行单元,通过调用Linux系统提供的pthread库中的函数来创建和管理线程。

  • 包含头文件:
#include<pthread.h>
  • 定义线程函数:

线程函数是线程实际执行的函数,可以是任何可以被调用的函数。线程函数的原型如下:

void*thread_function(void* arg);

其中

arg

是传递给线程函数的参数,可以是任何类型的数据。线程函数的返回值为

void*

类型,可以返回任何类型的数据。

  • 创建线程:

创建线程需要调用

pthread_create

函数。该函数的原型如下:

intpthread_create(pthread_t* thread,constpthread_attr_t* attr,void*(*start_routine)(void*),void* arg);

参数类型描述

thread
pthread_t *

用于存储新线程标识符的指针

attr
const pthread_attr_t *

用于指定新线程的属性,如栈大小、调度策略等,可以为 NULL,表示使用默认属性

start_routine
void *(*)(void *)

新线程的起始函数,需要返回 void 指针类型的结果,并且带有一个 void 指针类型的参数

arg
void *

传递给新线程起始函数的参数,可以为 NULL返回值

int

0 表示成功,非 0 表示失败,错误代码保存在

errno


🚩 注意:在调用 pthread_create() 函数之后,新线程的执行与调用线程并行进行,它们之间没有特定的执行顺序。

下面是一个创建线程的例子:

#include<stdio.h>#include<pthread.h>void*thread_func(void*arg){int i;for(i =0; i <5; i++){printf("这是线程函数,arg=%d, i=%d\n",*(int*)arg, i);sleep(1);}pthread_exit(NULL);}intmain(){pthread_t tid;// 线程标识符int arg =123;// 传递给线程函数的参数// 创建新线程if(pthread_create(&tid,NULL, thread_func,&arg)!=0){printf("线程创建失败!\n");return1;}// 等待线程结束并回收资源if(pthread_join(tid,NULL)!=0){printf("线程回收失败!\n");return1;}printf("线程结束!\n");return0;}

图片3

三、 线程的终止

线程的终止有两种方式:自然终止强制终止

线程的自然终止是指线程执行完它的工作后自动退出,而强制终止是指在程序运行过程中,主线程或其他线程显式地终止一个正在运行的线程。

线程自然终止

线程可以通过调用

pthread_exit

函数来实现自然终止。

pthread_exit

函数的原型如下:

voidpthread_exit(void*retval);
pthread_exit

函数 无返回值,其中,参数

retval

是线程的退出状态,可以通过

pthread_join

函数获取。

下面是一个简单的例子,演示如何使用

pthread_exit

函数终止一个线程:

#include<stdio.h>#include<pthread.h>void*thread_func(void*arg){int i;for(i =0; i <5; i++){printf("这是线程函数,i=%d\n", i);sleep(1);}pthread_exit((void*)"线程正常结束!");}intmain(){pthread_t tid;// 线程标识符// 创建新线程if(pthread_create(&tid,NULL, thread_func,NULL)!=0){printf("线程创建失败!\n");return1;}// 等待线程结束并回收资源void*retval;if(pthread_join(tid,&retval)!=0){printf("线程回收失败!\n");return1;}printf("%s\n",(char*)retval);printf("线程结束!\n");return0;}

上面的示例程序中,我们在线程函数中调用

pthread_exit

函数来终止线程,并返回一个字符串作为退出状态。

在主线程中,我们使用

pthread_join

函数等待线程结束,并通过指针

retval

获取线程的退出状态。

线程强制终止

在Linux中,线程的强制终止可以使用

pthread_cancel

函数来实现。

pthread_cancel

函数的原型如下:

intpthread_cancel(pthread_t thread);

其中,参数

thread

是要取消的线程标识符。当

pthread_cancel

函数被调用时,被取消的线程将立即退出。
参数类型描述

thread
pthread_t

要取消的线程标识符返回值

int

0 表示成功,非 0 表示失败,错误代码保存在

errno 


🚩注意:调用 pthread_cancel() 函数只是向指定线程发送一个取消请求,让指定线程尽快退出执行,而不会立即终止它的执行。

线程在接收到取消请求后,可以通过调用

pthread_setcancelstate() 

pthread_setcanceltype()

函数来指定如何响应请求,这里不再展开说明。

下面是一个简单的例子,演示如何使用

pthread_cancel

函数强制终止一个线程:

#include<stdio.h>#include<pthread.h>void*thread_func(void*arg){int i;for(i =0; i <5; i++){printf("这是线程函数,i=%d\n", i);sleep(1);}pthread_exit((void*)"线程正常结束!");}intmain(){pthread_t tid;// 线程标识符// 创建新线程if(pthread_create(&tid,NULL, thread_func,NULL)!=0){printf("线程创建失败!\n");return1;}// 等待一段时间后强制终止线程sleep(2);if(pthread_cancel(tid)!=0){printf("线程取消失败!\n");return1;}// 等待线程结束并回收资源void*retval;if(pthread_join(tid,&retval)!=0){printf("线程回收失败!\n");return1;}if(retval == PTHREAD_CANCELED){printf("线程被取消!\n");}else{printf("%s\n",(char*)retval);}printf("线程结束!\n");return0;}

上面的示例程序中,主线程调用了

pthread_cancel

函数,强制终止了子线程。

在子线程函数中,我们使用

pthread_exit

函数返回了一个字符串,如果子线程正常结束,那么在主线程中打印出来的将是这个字符串;如果子线程被强制终止,那么在主线程中打印出来的将是

线程被取消!

图片4

  • 🙈不是这个啦
  • 我是想说,前面好几次都提到了线程回收, 你是不是忘了告诉我了
  • 👧 不好意思哈,一下子没忍住就说出来了

四、线程的回收

使用

pthread_join

函数等待线程结束。该函数需要两个参数:线程标识符和指向线程返回值的指针。

intpthread_join(pthread_t thread,void**value_ptr);

参数类型描述

thread
pthread_t

要等待的线程标识符

value_ptr
void **

用于获取线程的退出状态的指针,可以为 NULL,表示不关心退出状态返回值

int

0 表示成功,非 0 表示失败,错误代码保存在

errno 


🚩 注意:调用 pthread_join() 函数会阻塞当前线程,直到指定的线程终止为止。

如果指定的线程已经终止,那么该函数会立即返回,并且不会阻塞。

另外,线程的退出状态只有在 pthread_join() 调用成功时才能被获取,否则 value_ptr 指向的值是未定义的。

图片5

如果线程终止后,其它线程没有调用 pthread_join()函数来回收该线程,这个线程会变成僵尸线程,会浪费系统资源;若僵尸线程积累过多,那么会导致应

用程序无法创建新的线程。

图片6

五、线程的分离

可以使用

pthread_detach

函数将线程分离。

pthread_detach

函数的原型如下:

intpthread_detach(pthread_t thread);

参数类型描述threadpthread_t要分离的线程标识符返回值int0 表示成功,非 0 表示失败,错误代码保存在 errno 中
调用

pthread_detach() 

函数将使得指定线程在退出时自动释放其相关资源,而不需要其他线程调用

pthread_join() 

函数来等待它的退出并回收资源。

如果指定的线程已经被分离或者已经退出,那么调用 pthread_detach() 函数将返回一个错误。

下面是一个简单的例子,演示如何使用

pthread_detach

函数将线程分离:

#include<stdio.h>#include<pthread.h>void*thread_func(void*arg){int i;for(i =0; i <5; i++){printf("这是线程函数,i=%d\n", i);sleep(1);}pthread_exit((void*)"线程正常结束!");}intmain(){pthread_t tid;// 线程标识符// 创建新线程if(pthread_create(&tid,NULL, thread_func,NULL)!=0){printf("线程创建失败!\n");return1;}// 分离线程if(pthread_detach(tid)!=0){printf("线程分离失败!\n");return1;}printf("线程已经分离,将自动回收资源!\n");// 程序结束return0;}

上面的示例程序中,我们在创建线程之后立即将线程分离,并打印一条提示信息,告诉用户线程已经分离,将在退出时自动回收资源。

当运行上面的程序时,可以看到如下输出:

线程已经分离,将自动回收资源!
这是线程函数,i=0
这是线程函数,i=1
这是线程函数,i=2
这是线程函数,i=3
这是线程函数,i=4

可以看到,程序创建了一个新线程,并立即将它分离。在子线程中,我们打印了5个字符串,每个字符串间隔1秒。

在主线程中,我们打印了一条提示信息,告诉用户线程已经分离,将在退出时自动回收资源。最后,程序正常结束,没有调用

pthread_join

函数。

小结

我们已经介绍了Linux线程的创建、终止、回收、分离等基本操作。

在实际编程中,我们可能还需要使用一些其他的函数和技巧,例如互斥锁、条件变量、信号量、读写锁等

图片7

👧 欲知后事如何,请听下回分解!


📢欢迎各位 👍点赞 ⭐收藏 📝评论,如有错误请留言指正,非常感谢!

标签: linux 程序员 运维

本文转载自: https://blog.csdn.net/Happy_HZW/article/details/129723449
版权归原作者 知微之见 所有, 如有侵权,请联系我们删除。

“Linux线程 | 创建 终止 回收 分离”的评论:

还没有评论