linux---线程的深入了解

线程


什么是线程

在一个程序里的一个执行路线就叫做线程。线程是一个进程内部的控制序列。
一个进程至少有一个线程。

进程与线程(进程与线程总结
进程的多线程共享
  • 地址空间
  • 文件描述符
  • 信号的处理方式
  • 当前工作目录
  • 用户ID和组ID
线程优点:
  • 创建一个新线程的代价要比创建一个新进程小得多。
  • 与进程之间的切换相比,线程之间的切换需要操作系统做的工作要少很多。
  • 线程占用的资源要比进程少很多。
  • 计算密集型应用,为了能在多处理器系统上运⾏行,将计算分解到多个线程中实现。
  • I/O密集型应用,为了提高性能,将I/O操作重叠。线程可以同时等待不同的I/O操作。
线程缺点:
  1. 性能损失:不能共享同一个处理器。如
    果计算密集型线程的数量比可用的处理器多,那么可能会有较大的性能损失。
    。 2. 健壮性降低:线程间的共享导致,线程之间缺乏保护。
  2. 缺乏访问控制:进程是访问控制的基本粒度,在一个线程中调用某些OS函数会对整个进程造成影响。
  3. 编程、调试难度高。

线程控制


POSIX线程库
  1. 与线程有关的函数构成了一个完整的系列,绝⼤大多数函数的名字都是以“pthread_”开头。
  2. 头文件pthread.h
  3. 链接这些线程函数库时要使用编译器命令的“-lpthread”选项。
创建线程
int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*star
t_routine)(void*), void *arg);

thread:返回线程ID。
attr:设置线程的属性,NULL表示默认属性。
start_routine:函数地址,线程启动后执行的函数。
arg:传给线程启动函数的参数
返回值:成功返回0,失败返回错误码。

线程ID和进程ID
  • 在Linux中,线程被称为轻量级进程(Light Weighted Process),每一个用户态的线程,在内核中都对应一个调度实体,也拥有自己的进程描述符(task_struct结构体)。
  • 没有线程之前,一个进程对应内核⾥里的一个进程描述符,对应一个进程ID。但是引入线程概念之后,情况发生了变化,一个用户进程下管辖N个用户态线程,每个线程作为一个独立的调度实体在内核态都有自己的进程描述符,进程和内核的描述符一下子就变成了1:N关系。
  • 所以,Linux内核引入了线程组的概念。

多线程的进程,又被称为线程组,线程组内的每一个线程在内核之中都存在一个进程描述符
(task_struct)与之对应。进程描述符结构体中的pid,表面上看对应的是进程ID,其实不然,它
对应的是线程ID;进程描述符中的tgid,含义是Thread Group ID,该值对应的是用户层面的进程ID。

用户态系统调用内核进程描述符中对应的结构
线程IDpid_t getpid(void)pid_t pid
进程IDpid_t getpid(void)pid_t tgid
  1. 内核在创建第一个线程时,将线程组的ID设为第一个线程的线程ID。所以线程组内存在一个线程ID等于进程ID,该线程为线程组的主线程。
  2. 至于线程组其他线程的ID则有内核负责分配,其线程组ID总是和主线程的线程组ID一致,无论是主线程直接创建线程,还是创建出来的线程再次创建线程,都是这样。
  3. 线程和进程不一样,进程有父进程,但是线程都是对等关系。
线程终止
  1. 从线程函数return。主线程不适用。
  2. 调用pthread_exit(无返回值)终止自己。
  3. 调用pthread_cancel(成功返回0,错误返回错误码)终止统一进程中的另一个线程。

线程等待和分离


为什么要线程等待?

已经退出的线程,空间不会被释放,创建的新线程无法使用退出线程的地址空间。

线程等待

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

thread:线程ID
value_ptr:指向一个指针,后者指向线程返回值
返回值:成功返回0,失败返回错误码

调用该函数的线程将挂起等待,直到id为thread的线程终止。thread线程以不同的方法终止,通过pthread_join得到的终止状态是不同的。

  1. return返回:value_ptr所指向的单元存放thread线程函数的返回值
  2. 被pfhread_cancel异常终止:value_ptr所指向的单元存放常数PTHRAD_CANCELED
  3. pthread_exit自行终止:value_ptr所指向的单元存放传给pthread_exit的参数
  4. value_ptr也可以为NULL
线程分离
  • 默认情况下,新创建的线程是joinable的,线程退出后,需要对其进行pthread_join操作,否则无法
    释放资源,从而造成内存泄漏。
    • 如果不关心线程的返回值,join是一种负担,这个时候,我们可以告诉系统,当线程退出时,自动释放线程资源。
int pthread_detach(pthread_t thread);

可以是线程组内其他线程对目标线程进行分离

pthread_detach(pthread_self());

也可以是线程自己分离
jionable和分离是冲突的,一个线程不能既是joinable又是分离的

线程同步与互斥


同步,又称直接制约关系,是指多个线程(或进程)为了合作完成任务,必须严格按照规定的 某种先后次序来运行。
互斥,又称间接制约关系,是指系统中的某些共享资源,一次只允许一个线程访问。当一个线程正在访问该临界资源时,其它线程必须等待。

  1. 互斥是指某一资源同时只允许一个访问者对其进行访问,具有唯一性和排它性。但互斥无法限制访问者对资源的访问顺序,即访问是无序的。
  2. 同步是指在互斥的基础上(大多数情况),通过其它机制实现访问者对资源的有序访问。
  3. 同步其实已经实现了互斥,所以同步是一种更为复杂的互斥。
  4. 互斥是一种特殊的同步。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值