Linux多线程

进程与线程的区别

进程是一个运行中的程序,站在操作系统的角度,进程就是一个运行中的长须的描述-PCB(进程控制块)。
线程是轻量级的进程。在传统的操作系统中,pcb就是进程,而tcb是线程控制块,每个线程有他自己的tcb。但是在Linux下,因为线程是通过进程的pcb描述实现的(task_struct结构体),因此Linux下的pcb实际上是一个线程组,并且因为这些线程共用一个虚拟地址空间,因此也把Linux下的线程成为轻量级进程,相较于传统pcb更加的轻量化。
进程是资源分配的基本单位,线程是CPU调度的基本单位。
进程有自己的独立地址空间,每启动一个进程,系统就会为它分配地址空间,建立数据表来维护代码段、堆栈段和数据段,这种操作非常昂贵。
线程是共享进程中的数据的,使用相同的地址空间,因此CPU切换一个线程的花费远比进程要小很多,同时创建一个线程的开销也比进程要小很多。
线程之间的通信更方便,同一进程下的线程共享全局变量、静态变量等数据,而进程之间的通信需要使用进程间通信方式(IPC)进行。

  • 多线程的优点:
    因为共用同一块虚拟地址空间,因此线程间通信更加灵活方便(可以使用全局变量、传参等方式)
    线程间共用进程的大部分资源,因此线程的创建与销毁成本更低。
    也因为线程间共用进程的大部分资源,所以线程的切换调度成本更低。
  • 多线程缺点:
    线程间缺乏访问控制,某些系统调用以及异常是针对整个进程产生效果的。
  • 多进程优点:
    进程间相互独立,因此稳定、健壮性更高,适用于对主程序安全稳定性要求更高的场景,例如shell、服务器。

线程

线程共享的资源

线程共用所属进程的同一地址空间,因此代码段、数据段(虚拟地址空间)都是共享的,定义一个函数,则在各线程中都可以调用,定义一个全局变量,在各线程中都可以访问,除此之外,各线程还共享以下进程资源和环境:

  • 文件描述符表
  • 每种信号的处理方式(SIG_ IGN忽略、SIG_ DFL默认或者自定义的信号处理函数)
  • 当前工作目录
  • 用户id和组id
线程独有的资源

线程共享进程的数据,但也有一部分自己独有的数据:

  • 线程ID,即线程标识符
  • 寄存器(存放上下文数据等)
  • errno
  • 信号屏蔽字(阻塞信号集合)
  • 调度优先级
线程属性pthread_attr_t结构体
typedef struct{
   
	int detachstate;                //线程的分离状态
	int schedpolicy;                //线程调度策略
	struct sched_param schedparam;  //线程的调度参数
	int inheritsched;               //线程的继承性
	int scope;                      //线程的作用域
	size_t guardsize;               //线程栈末尾的警戒缓冲区大小
	int stackaddr_set;              //线程的栈设置
	void* stackaddr;                //线程栈的位置(最低地址)
	size_t stacksize;               //线程栈的大小
} pthread_attr_t; 

属性值不能直接设置,须使用相关函数进行操作,初始化pthread_attr_init,这个函数必须在pthread_create函数之前调用。
之后须用pthread_attr_destroy函数来释放资源。
线程属性主要包括如下属性:作用域(scope)、栈尺寸(stack size)、栈地址(stack address)、优先级(priority)、分离的状态(detached state)、调度策略和参数(scheduling policy and parameters)。
默认属性为非绑定、非分离、缺省的堆栈、与父进程同样级别的优先级。

线程创建:
#include <pthread.h>
int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg);

pthread_t:无符号长整型
*thread:线程地址空间,用户态县城描述信息/操作句柄。线程地址空间在进程虚拟地址空间中的首地址。
(pcb中的pid为轻量级进程ID,而tgid为进程ID,即线程组ID,值默认等于主线程的pid)
pthread_attr_t *attr:线程的属性参数,通常置空
void *(*start_routine) (void *), void *arg:线程入口函数,*arg为传递给线程的参数

线程终止:
  1. 线程见自己的入口函数运行完毕return退出,在主函数main函数中退出的是进程。
  2. void pthread_exit(void *retval); 退出调用线程
  3. int pthread_cancel(pthread_t thread); 取消一个指定线程,成功返回0,失败返回错误编号
线程等待:

默认情况下,线程退出后也不会完全释放资源,需要被其他线程等待,线程等待即指等待一个指定的线程退出,retval获取这个退出线程的返回值,并且回收资源。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值