Linux (十一) 线程控制(线程的创建,等待,分离)

POSIX线程库
与线程有关的函数构成了一个完整的系列,绝大多数函数名字都是以“Pthread_”打头的
要是用这些函数库,要通过引入头文件
连接这些线程函数库时要使用编译器命令的“-lpthread”选项

创建线程

int pthread_creat(pthread_t *thread,const pthread_attr_t *attr,void *(*start_routine)(void*),void *arg);

功能:创建一个新的线程
参数:
    thread:返回线程ID
    attr:设置线程属性,attr为NULL表示使用默认属性
    start_toutine:是个函数地址,线程启动后要执行的函数
    arg:传给线程启动函数的参数
返回值:成功返回0;失败返回错误码

进程ID和线程ID
在Linux中,目前的线程实现是Native POSIX Thread Libaray,简称NPTL。在这种实现下,线程又被称为轻量级进程(LWP),每一个用户态的线程,在内核中都对应一个调度实体,也拥有自己的进程描述符(task_struct结构体)
没有线程之前,一个进程对应内核里的一个进程描述符,对应一个进程ID。但是引入线程概念之后,情况发生了改变,一个用户进程下管理N个用户态线程,每个线程作为独立的调度实体在内核态都有自己的进程描述符,进程和内核的描述符一下子变成了1:N的关系,POSIX标准有要求进程内所有的线程调用getpid函数时返回相同的进程ID,如何解决这个问题呢?
Linux内核引入了线程组的概念

多线程的进程,又被称为线程组,线程组内的每个线程在内核中都存在一个进程描述符(task_struct)与之对应。进程描述符结构体中的pid 表示的是进程组ID

其中LWP叫做轻量级进程,也就是线程ID,即gettid系统调用的返回值
其中主线程的线程ID也就是进程的ID
另外线程和进程不一样,进程有父进程的概念,但在线程组里面,所有线程都是对等关系
我们可以调用函数获得线程自身ID

pthread_t pthread_self(void);

其实pthread_t类型的线程ID,本质上就是一个程序地址空间上的一个地址

如果需要只终止某个线程而不终止整个进程,可以有三种方法
1:从线程函数return。这种方法对主线程不适用,从main函数return相当于调用exit
2:线程可以调用pthread_exit终止自己。
3:一个线程可以调用pthead_cancel终止同一进程的另一个线程
pthread_exit函数

pthread_exit函数

功能:线程终止
原型:
    void pthread_exit(void *value_ptr);
参数
    value_ptr :value_ptr不要指向一个局部变量
返回值:无返回值,跟进城一样,线程结束时候无法返回它的调用者

需要注意,pthread_exit或者return返回的指针所指向的内存单元必须是全局的或者用malloc分配的,不能在线程函数的栈上分配,因为当其他线程得到这个返回指针时线程函数已经退出了。

pthread_cancle函数
功能:取消一个执行中的线程

线程等待与分离

线程等待
为什么需要线程等待呢?
已经退出的线程,其空间没有被释放,仍然在进程的地址空间内。创建新的线程不会复用刚才退出线程的地址空间,这样就会使系统资源越来越少。

功能:等待线程结束
原型:
    int pthread_join(pthread_t thread,void **value_ptr);
参数:
    thread:线程ID
    value_ptr:它指向一个指针,后者指向现成的返回值
返回值:成功返回0;失败返回错误码

调用该函数的线程就会挂起等待,直到id为thread的线程终止。如果thread线程以不同的方法终止,那么通过这个函数所得到的终止状态是不同的:
1:如果通过return返回,value_ptr所指向的单元里存放的是thread线程函数的返回值。
2:如果thread线程被别的线程调用Pthread_cancel异常终止,value_ptr所指向的单元里存放的是常数PTHREAD_CANCELED
3:如果thread线城市自己调用pthread_exit终止的,那么value_ptr所指向的单元里存放的是传给pthread_exit的参数。
4:如果对thread线程终止状态不感兴趣,可以传NULL给value_ptr参数

线程分离
默认情况下,新创建的线程是会joinable的,线程退出后,需要对进程进行pthread_join操作,否则无法释放资源从而进行系统泄漏
如果不关心线程的返回值,join是一种负担,这个时候我们就要告诉系统,当进程退出时,自动释放线程资源

int pthread_detach(pthread_t thread);

当想要对自己进行分离时就传Pthread_self()

一个线程不能是又等待,又分离的

猜你喜欢

转载自blog.csdn.net/mignatian/article/details/80028557