前言: 最近一直在疯狂学习, 之前也不太了解线程, 现在基本都掌握了. 如果你之前也不知道线程, 也不知道进程和线程的区别等等, 这一篇博客带你完全掌握, 不掌握不要钱, 哈哈哈!
一, 线程概念
介绍概念之前, 先画个图吧, 依旧是全博客园最丑图, 不接受反驳!
简单说明一下: 进程在其内部创建线程, 线程有自己的 PCB, 但没有独立的地址空间.
线程和进程具有以下特征和区别:
LWP:light weight process 轻量级的进程, 本质仍是进程(在 Linux 环境下)
进程: 独立地址空间, 拥有 PCB
线程: 也有 PCB, 但没有独立的地址空间(共享)
区别: 在于是否共享地址空间. 独居(进程); 合租(线程).
Linux 下: 线程: 最小的执行单位(CPU 分配时间轮片是通过线程来实现的)
进程: 最小分配资源单位, 可看成是只有一个线程的进程
参考:《Linux 内核源代码情景分析》 ---- 毛德操
二, 线程共享资源
1. 文件描述符表
2. 每种信号的处理方式
3. 当前工作目录
4. 用户 ID 和组 ID
5. 内存地址空间 (.text/.data/.bss/heap / 共享库)
三, 线程非共享资源
1. 线程 id
2. 处理器现场和栈指针(内核栈)
3. 独立的栈空间(用户空间栈)
4.errno 变量
5. 信号屏蔽字
6. 调度优先级
四, 线程的优缺点
优点: 1. 提高程序并发性 2. 开销小 3. 数据通信, 共享数据方便
缺点: 1. 库函数, 不稳定 2. 调试, 编写困难, gdb 不支持 3. 对信号支持不好
优点相对突出, 缺点均不是硬伤. Linux 下由于实现方法导致进程, 线程差别不是很大.
五, 线程相关函数
在学习线程函数之前, 再说点题外话. 类 Unix 系统中, 早期是没有 "线程" 概念的, 80 年代才引入, 借助进程机制实现出了线程的概念. 因此在这类系统中, 进程和线程关系密切. 所以可以将线程相关函数与进程函数进行对比学习.
pthread_self 函数
功能: 获取线程 ID. 其作用对应进程中 getpid() 函数.
原型: pthread_t pthread_self(void);
返回值: 成功: 0; 失败: 无!
线程 ID:pthread_t 类型, 本质: 在 Linux 下为无符号整数(%lu), 其他系统中可能是结构体实现
线程 ID 是进程内部, 识别标志.(两个进程间, 线程 ID 允许相同)
pthread_create 函数
功能: 创建一个新线程. 其作用, 对应进程中 fork() 函数.
原型: int pthread_create(pthread_t *thread, const pthread_attr_t *attr,void *(*start_routine) (void *), void *arg);
返回值: 成功: 0; 失败: 错误号 -----Linux 环境下, 所有线程特点, 失败均直接返回错误号.
参数说明:
pthread_t: 当前 Linux 中可理解为: typedef unsigned long int pthread_t;
参数 1: 传出参数, 保存系统为我们分配好的线程 ID
参数 2: 通常传 NULL, 表示使用线程默认属性. 若想使用具体属性也可以修改该参数.
参数 3: 函数指针, 指向线程主函数(线程体), 该函数运行结束, 则线程结束.
参数 4: 线程主函数执行期间所使用的参数. 跟参数三关联.
注意: 链接线程库 -lpthread
写一个简单程序, 演示这两个函数用法:
- #include<stdio.h>
- #include<unistd.h>
- #include<pthread.h>
- void *tfn(void *arg)
- {
- printf("child thread%lu\n",pthread_self());
- return NULL;
- }
- int main()
- {
- pthread_t tid;
- pthread_create(&tid,NULL,tfn,NULL);
- sleep(1);
- printf("main thread:%lu\n",pthread_self());
- return 0;
- }
- View Code
编译: gcc pthread_cre.c -lpthread, 记得链接线程库 -lpthread
pthread_exit 函数
功能: 将单个线程退出 相当于 exit
原型: void pthread_exit(void *retval);
参数: retval 表示线程退出状态, 通常传 NULL
pthread_join 函数
功能: 阻塞等待线程退出, 获取线程退出状态 其作用, 对应进程中 wait(),waitpid() 函数.
原型: int pthread_join(pthread_t thread, void **retval);
参数: thread: 线程 ID ([注意] : 不是指针);retval: 存储线程结束状态.
pthread_detach 函数
功能: 实现线程分离 线程独有的, 没有进程的相关函数与之对应
原型: int pthread_detach(pthread_t thread);
线程分离状态: 指定该状态, 线程主动与主控线程断开关系. 线程结束后, 其退出状态不由其他线程获取, 而直接自己自动释放. 网络, 多线程服务器常用.
重点: 分离状态的线程就不需要回收了!!! 重要的事情说三遍, 三遍, 三遍!!!
pthread_cancel 函数
功能: 杀死 (取消) 线程 其作用, 对应进程中 kill() 函数.
原型: int pthread_cancel(pthread_t thread);
[注意] : 线程的取消并不是实时的, 而有一定的延时. 需要等待线程到达某个取消点(检查点).
六, 控制原语对比
就是就是将进程相关函数与线程函数, 进行对比来记忆:
进程 线程
- fork pthread_create
- exit pthread_exit
- wait pthread_join
- kill pthread_cancel
- getpid pthread_self
总结: 欢迎评论, 交流与学习.
来源: https://www.cnblogs.com/liudw-0215/p/9682962.html