Linux下线程

来源:互联网 发布:芙丽芳丝洗面奶知乎 编辑:程序博客网 时间:2024/06/05 14:44

此文讲述的线程为Linux下,其线程库函数是由POSIX标准定义的,称为POSIX thread或者pthread。在Linux上线程函数位于libpthread共享库中,因此在编译时要加上-lpthread选项。

线程概念

进程在各自独立的地址空间中运行,进程之间共享数据需要用mmap或者进程间通信机制,而有些情况需要在⼀个进程中同时执行多个控制流程,这时候线程就派上了用场,比如实现⼀个图形界面的下载软件,一方面需要和用户交互,等待和处理用户的鼠标键盘事件,另⼀方面又需要同时下载多个文件,等待和处理从多个网络主机发来的数据,这些任务都需要一个“等待-处理”的循环,可以用多线程实现,⼀个线程专门负责与用户交互,另外几个线程每个线程负责和⼀个网络主机通信。由于同⼀进程的多个线程共享同⼀地址空间,因此Text Segment、 Data Segment都是共享的,如果定义⼀个函数,在各线程中都可以调用,如果定义一个全局变量,在各线程中都可以访问到,除此之外,各线程还共享以下进程资源和环境:
1. ⽂件描述符表
2. 每种信号的处理⽅式(SIG_IGN、 SIG_DFL或者⾃定义的信号处理函数)
3. 当前⼯作⽬录
4. ⽤户id和组id
但有些资源是每个线程各有⼀份的:
1. 线程id
2. 上下⽂,包括各种寄存器的值、程序计数器和栈指针
3. 栈空间
4. errno变量
5. 信号屏蔽字
6. 调度优先级
其中的上下文信息和私有栈尤为重要;在Linux下无真正意义的线程,而是轻量级进程,因此线程为调度的基本单位,而进程则是承担分配资源功能。

线程控制

创建线程:

这里写图片描述

终止线程:

这里写图片描述

等待线程:

这里写图片描述

三个函数都为pthread.h中定义,其中要注意的是:

创建:

返回值:成功返回0,失败返回错误号pthread库的函数都是通过返回值返回错误号,虽然每个线程也都有一个错误号errno,但这是为了兼容其它函数接口而提供的,pthread库本身并不使用它,通过返回值返回错误码更加清晰;新的线程所执行的代码由我们传给pthread_create的函数指针start_routine决定;

终止:

如果需要只终止某个线程而不终止整个进程,可以有三种方法:
1. 从线程函数return。这种方法对主线程不适用,从main函数return相当于调用exit。
2. 一个线程可以调用pthread_cancel终⽌同⼀进程中的另⼀个线程。
3. 线程可以调⽤pthread_exit终止自己。
也就是指,当直接使用exit时,会将整个进程直接终止掉。

等待:

调用该函数的线程将挂起等待,直到id为thread的线程终止。 thread线程以不同的方法终止,通过pthread_join得到的终止状态是不同的,总结如下:
1. 如果thread线程通过return返回,value_ptr所指向的单元里存放的是thread线程函数的返回值。
2. 如果thread线程被别的线程调用pthread_cancel异常终掉,value_ptr所指向的单元里存放
的是常数PTHREAD_CANCELED。
3. 如果thread线程是自己调用pthread_exit终止的,value_ptr所指向的单元存放的是传给
pthread_exit的参数。 如果对thread线程的终止状态不感兴趣,可以传NULL给value_ptr
参数。

代码测试:

这里写图片描述
这里写图片描述

线程分离与结合属性

线程是可结合的或者是可分离的,⼀个可结合的线程能够被其他线程收回其资源和杀死。在被其他线程回收之前,它的存储器资源(例如私有栈)是不释放的; 相反⼀个分离的线程是不能被其他线程回收或杀死的,它的存储器资源在它终⽌时由系统⾃动释放。
而一个线程默认属性为可结合,每个可结合的线程都需要被显示的调用pthread_join回收,否则则会出现类似进程僵尸的现象。而在进行等待时,如果线程没有返回则会仅从堵塞,如果你不想令其可结合,可调用pthread_detach(thread_id)让线程分离,如此,该线程运⾏结束后会⾃动释放所有资源。

原创粉丝点击