创作不易,本篇文章如果帮助到了你,还请点赞 关注支持一下♡>𖥦<)!!
主页专栏有更多知识,如有疑问欢迎大家指正讨论,共同进步!
🔥Linux系列专栏:Linux基础 🔥给大家跳段街舞感谢支持!ጿ ኈ ቼ ዽ ጿ ኈ ቼ ዽ ጿ ኈ ቼ ዽ ጿ ኈ ቼ ዽ ጿ ኈ ቼ
目录
- 一、线程的概念
- 二、线程和进程
- 进程退化
- 多个线程在进程中共享资源有哪些?
- 二、线程函数
- 创建线程
- 获取线程id
- 线程回收
- 线程退出
- 线程取消
- 设置线程分离
一、线程的概念
线程是操作系统能够进行调度和执行的最小单位。它是进程内执行的一个独立单元,与同一进程中的其他线程共享进程的地址空间和系统资源。
线程能减少程序在并发执行时所付出的时空开销,使操作系统具有更好的并发性。
二、线程和进程
一般情况下进程包含线程,线程比进程更轻量(体积更小,开销更小)
进程是最小的分配资源单位,线程是最小的调度单位
线程不分配内存,线程创建于进程中,与进程共享资源,访问进程的内存,完成特定任务
类 Unix 系统中,早期是没有“线程”概念的,80 年代才引入,借助进程机制实现出了线程的概念。因此在这类系统中,进程和线程关系密切
轻量级进程(light-weight process)也有 PCB,创建线程使用的底层函数和进程一样,都是 clone
从内核里看进程和线程是一样的,都有各自不同的 PCB,但是 PCB 中指向内存资源的三级页表是相同的
进程可以退化成线程
线程可看做寄存器和栈的集合,线程可以占用时间片使用cpu,可以通过保存和恢复处理器现场避免寄存器冲突,所以线程是一个合格的调度单位。
在 linux下,线程最是小的执行单位;进程是最小的分配资源单位
多线程可以共享资源,减少内存开销
进程退化
如果进程中创建了新的线程,那么进程原本的执行单元成为主控线程,新创建的成为普通线程,便于区分和理解。
线程分为内核级线程KLT和用户级线程ULT
cpu会给每个内核级线程分配内核对象,与进程一样获取cpu
- 优点:内核级线程可以得到更多的系统资源,缩短任务完成时间
- 缺点:所有的线程资源分配、访问和上下文切换都需要系统干预,开销较大
系统无法识别用户级线程,无法将资源分发给普通线程,只会给用户级进程
普通线程虽然无法直接被系统分发资源,但是可以使用cpu(可以主线程sleep(0)放弃时间片,给同进程下的普通进程时间片)
优点:用户级线程的创建、撤销和切换与OS内核无关,由用户空间中的线程库完成,系统调度开销小
多个线程在进程中共享资源有哪些?
- 1.全局变量
- 2.文件描述符
- 3.PCB
- 4.堆空间
- 5.信号处理行为
非共享资源:
- 1.线程栈
- 2.TCB
- 3.优先级指针·
- 4.信号屏蔽字
- 5.errno全局变量
二、线程函数
创建线程
int pthread_create(pthread_t *tid, const pthread_attr_t *attr, void *(*start_rountn)(void *), void *arg);
返回值:
- 创建成功 返回0
- 创建失败 返回errno
参数:
- tid:传出参数,表示为创建的子线程id
- attr:线程属性,传
NULL
代表默认属性 - start_rountn:子线程回调函数,函数指针,为线程工作地址。
ptherad_create
函数返回时,该函数会被自动调用 - arg:
start_rountn
函数参数,系统创建线程后调用start_rountn
后把arg传入twk函数中
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
void* job(void* arg)
{
//子线程
while(1)
{
printf("child thread running...\n");
sleep(1);
}
}
int main()
{
//主线程
pthread_t tid;
int err;
if( (err = pthread_create(&tid,NULL,job,NULL) ) > 0)
{
printf("thread_create failed:%s\n",strerror(err));
exit(0);
}
while(1)
{
printf("parent thread running...\n");
sleep(1);
}
return 0;
}
获取线程id
pthread_t pthread_self();
返回值:
- 本线程id
主线程创建成功后传出tid,与普通线程内部获取的tid 值相等,但是不等价
线程内部id即pthread_self()
可以保证线程当前有效性,但是其他线程中的tid即创建线程时传出的tid无法保证是否存活
线程回收
如果不回收将会引发僵线程(TCB)残留
void pthread_join(pthread_t tid,void** retval);
阻塞函数,线程未退出会等待,退出后立即回收
返回值:
- 创建成功返回0
- 创建失败返回errno
函数参数:
- tid:待回收的线程id
- reval:传出参数,为线程函数的返回值
线程退出
pthread_exit((void*)retval)
返回值:
- 创建成功返回0
- 创建失败返回errno
函数参数:
- reval:传出参数,为线程函数的返回值
线程取消
pthread_cancel(pthread_t tid);
返回值:
- 创建成功返回0
- 创建失败返回errno
函数参数:
- tid:待取消的线程id
可以将目标线程杀死,不能保证杀掉。只有目标线程内有系统调用如printf、sleep,才能杀掉
可以使用pthread_testcancel()
函数 触发一次系统调用,不进行其他操作。
被 cancel 杀死的线程再用 pthread_join 回收,返回值为-1
设置线程分离
int pthread_detach(pthread_t tid);
返回值:
- 成功:0
- 失败:errno
得到线程的返回值,使用回收态。系统自动回收使用分离态
大家的点赞、收藏、关注将是我更新的最大动力! 欢迎留言或私信建议或问题。 |
大家的支持和反馈对我来说意义重大,我会继续不断努力提供有价值的内容!如果本文哪里有错误的地方还请大家多多指出(●'◡'●) |