Linux:线程控制相关函数(POSIX线程库)

线程控制相关函数

POSIX线程库(用户级库)

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

1、创建线程(pthread_create)

函数使用

功能:创建一个新的线程
原型

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

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

错误检查:

  • 传统的一些函数是成功返回0,失败返回-1,并且对全局变量errno赋值以指示错误。
  • pthreads函数出错时不会设置全局变量errno(而大部分其他POSIX函数会这样做)。而是将错误代码通过返回值返回
  • pthreads同样也提供了线程内的errno变量,以支持其它使用errno的代码。对于pthreads函数的错误,建议通过返回值业判定,因为读取返回值要比读取线程内的errno变量的开销更小。

示例代码
Linux:线程控制相关函数(POSIX线程库)_第1张图片
输出结果和分析如下:
Linux:线程控制相关函数(POSIX线程库)_第2张图片

2、线程终止(三种方法)

如果需要只终⽌某个线程⽽不终⽌整个进程,可以有三种⽅法:

  1. 从线程函数内部return。 这种⽅法对主线程不适⽤,从main函数return相当于调⽤exit。也就是说我想要终止这个线程就在这个线程内部进行return,如果在主线程内部return则意味着进程退出。
    Linux:线程控制相关函数(POSIX线程库)_第3张图片
  2. 新线程可以调⽤pthread_ exit终⽌⾃⼰,pthread_ exit的参数就是最后该线程的返回值,是一个输出型参数。但是新线程不能调exit,主线程则可以调用exit,主线程调用exit说明进程退出,相当于return了,因为主线程可以等待所有新线程退出了它才退出。
    函数使用场景:
    Linux:线程控制相关函数(POSIX线程库)_第4张图片
  3. ⼀个线程可以调⽤pthread_ cancel终⽌同⼀进程中的另⼀个线程(一个线程可以被取消)
    函数使用场景:
    Linux:线程控制相关函数(POSIX线程库)_第5张图片
pthread_exit函数使用

功能: 线程终⽌
原型

void pthread_exit(void *value_ptr);

参数
value_ptr: value_ptr不要指向⼀个局部变量。
返回值: ⽆返回值,跟进程⼀样,线程结束的时候⽆法返回到它的调⽤者(⾃⾝)

这里的value_ptr参数的类型时void*,我们发现这里pthread_exit的参数和线程的返回值的类型一样,可以理解为,线程退出时如果调用pthread_exit函数来退出该线程,那么就是通过该函数的参数将返回值带出的,也就是圆括号里的参数就是该线程的返回值

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

pthread_cancel函数使用

功能: 取消⼀个执⾏中的线程
原型

int pthread_cancel(pthread_t thread);

参数
thread: 要终止线程的ID
返回值: 成功返回0;失败返回错误码

3、线程等待(pthread_join阻塞式等待)

线程等待函数使用

功能: 等待线程结束(默认阻塞式等待)
原型

int pthread_join(pthread_t thread, void **value_ptr);

参数
thread: 要等待的线程的ID
value_ptr: 它指向⼀个指针,后者指向线程的返回值,这个参数是为了看到新线程的返回值,因为线程的返回值是void*,因此我们传的时候要穿void**,也就是说这个参数是一个指向指针的指针。
返回值: 成功返回0;失败返回错误码
注意:线程在等待时只需要获取退出码就行,因为线程结束只有两种情况,代码跑完结果对和代码跑完结果不对,不会有异常退出的情况,因为一旦有一个线程出现了异常,整个进程都有可能会挂掉

调用该函数的线程将挂起等待,直到id为thread的线程终止(阻塞式等待)。 thread线程以不同的方法终止,通过pthread_join得到的终止状态是不同的,总结如下:

  1. 如果thread线程通过return返回,value_ ptr所指向的单元里存放的是thread线程函数的返回值。
  2. 如果thread线程被别的线程调用pthread_ cancel异常终掉,value_ ptr所指向的单元里存放的是常数PTHREAD_CANCELED(值为-1)。
  3. 如果thread线程是自己调用pthread_exit终止的,value_ptr所指向的单元存放的是传给pthread_exit的参数。
  4. 如果对thread线程的终止状态不感兴趣,可以传NULL给value_ ptr参数

示例代码:
Linux:线程控制相关函数(POSIX线程库)_第6张图片
运行结果及分析:
Linux:线程控制相关函数(POSIX线程库)_第7张图片

4、线程分离(pthread_detach)

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

函数使用:

功能: 分离一个线程

int pthread_detach(pthread_t thread);

参数: thread表示要分离的线程id,也可以线程自己分离自己
返回值: 成功返回0;失败返回错误码

这里我们需要注意的是,一个线程如果被分离了,那么这个线程就不能被创建该线程的线程所等待。
验证代码:
Linux:线程控制相关函数(POSIX线程库)_第8张图片
操作结果:
在这里插入图片描述

你可能感兴趣的:(Linux)