前言:最近一直在疯狂学习,之前也不太了解线程,现在基本都掌握了。如果你之前也不知道线程,也不知道进程和线程的区别等等,这一篇博客带你完全掌握,不掌握不要钱,哈哈哈!
一、线程概念
介绍概念之前,先画个图吧,依旧是全博客园最丑图,不接受反驳!
简单说明一下:进程在其内部创建线程,线程有自己的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 ",pthread_self()); return NULL; } int main() { pthread_t tid; pthread_create(&tid,NULL,tfn,NULL); sleep(1); printf("main thread:%lu ",pthread_self()); return 0; }
编译: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
总结:欢迎评论,交流与学习。