Linux 线程控制


前言

操作系统实际上并没有向上提供用于创建线程的接口,因此在上层就通过封装实现了线程控制对应所需的库函数,实现对线程的操作。


一、创建

创建线程的库函数:
int pthread_create(pthread_t *tid, pthread_attr_t *attr, void*(*routine)(void*), void *arg);

  • tid:获取线程id,也是线程的操作句柄
  • attr:设置线程属性,通常设置为NULL
  • routine:函数指针,线程入口函数,线程会去运行这个函数,运行完后线程退出
  • arg:传递给线程入口函数的参数
  • 返回值:成功返回0;失败返回非0,就是错误编号。但不是errno,errno是系统调用接口的错误编号,而pthread_create是库函数
  • 头文件:#include<pthread.h>
  • 创建的线程中,main函数是主线程,其他线程都是普通线程;创建的线程哪个先运行不一定,主要看cpu调度
  • 线程的有关操作都是库函数,所以在编译链接时,要链接pthread库
    在这里插入图片描述

创建线程代码:
在这里插入图片描述当我们运行一个程序时,都会有主线程,而主线程就是main函数,我们在主线程中创建一个普通线程,让普通线程完成指定功能,主线程不能先于普通线程退出。

我们都知道进程会有pid,一个进程中有一个或者多个线程,那么进程的这个pid是哪个线程的pid?

ps aux -L 查看轻量级进程
在这里插入图片描述
linux下的进程其实就是一个线程组。

在linux下,进程就是一个task_struct结构体,在这个结构体中有两个成员

    struct task_struct{
       pid_t pid;
       pid_t tgid;//线程组id
    }

task_struct->pid----轻量级进程(LWP)id
task_struct->tgid(线程组id)–所有轻量级进程拥有相同的线程组id 等于 主线程pid

什么是tid?

tid是线程id,是一个无符号的长整型数据,也是线程的操作句柄。每个线程被创建出来后,都会开辟一块空间,存储线程相关的信息,而tid就是存储线程信息的首地址。
在这里插入图片描述
所以查看tid时,要通过%p格式来查看。

pthread_t pthread_self(void):返回调用线程的tid,谁调用返回谁的
在这里插入图片描述

二、退出

  1. 在线程入口函数中return,线程入口函数运行完之后,线程就会自动退出。main函数return退出的是进程。

在普通线程中调用return,线程运行完之后,自动退出,不影响其他线程
在这里插入图片描述 主线程return退出的是进程,释放进程所有资源,所有线程退出
在这里插入图片描述

  1. void pthread_exit(void *retval)----退出调用线程,谁调用退出谁。retval是线程退出返回值。

主线程调用pthread_exit并不会使进程退出,只能使主线程退出,不影响其他线程,直至所有的线程退出,进程才会退出。
在这里插入图片描述普通线程调用pthread_exit库函数,普通线程退出
在这里插入图片描述

  1. int pthread_cancel(pthread_t tid)----退出指定线程,线程是被动退出的
    在这里插入图片描述

三、等待

等待 :等待指定的线程退出,获取退出线程返回值,回收资源。

一个线程被创建后,默认的情况下,退出时也不会自动释放资源。

每个线程都有一个属性(分离属性),默认是joinable状态,处于这个状态的线程退出后不会自动释放资源,退出后需要被其他线程等待获取其返回值并释放资源。

默认情况下,线程必须被等待;如果不等待,则造成资源泄漏

int pthread_join(pthread_t tid, void **retval);---- 等待指定的线程退出,获取返回值,这是一个阻塞函数,如果线程没有退出则一直等待。

  • tid:指定要等待的线程
  • retval:用于获取线程返回值
    在这里插入图片描述线程退出返回值是字符指针,不能是字符串首地址。因为字符串常量放在文字常量区,程序结束后由系统释放,指针retval指向字符串常量所在的地址。但是retval数组是在栈区开辟空间,并把字符串常量复制过去,retval数组指向的是在栈区存放字符串常量的位置,函数结束后,栈上的空间自动归还给系统,那么retval数组就成为野指针,就不能正确得到线程的返回值
    在这里插入图片描述
    注意:线程之间通过参数或者返回值传递数据极度需要注意数据生命周期,局部数据出了作用域空间就会被释放。

四、分离

分离:将线程的分离属性设置为detach状态(将joinable状态改为detach状态)

处于joinable状态的线程退出后,需要被其他线程等待获取其返回值并释放资源。
处于detach状态的线程退出之后,自动释放资源,不需要被等待。

使用场景:对线程的返回值不关心,也不想等待线程退出,就可以使用分离。

int pthread_detach(pthread_t tid);---- 将指定线程分离属性设置为detach状态
在这里插入图片描述
线程分离不一定需要其他线程设置,每个线程可以将自己进行线程分离,也就是在函数中调用pthread_detach函数,可以通过pthread_self获取线程本身的tid。
在这里插入图片描述

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值