linux 之线程基础 (二)、 线程相关API

2. 线程相关API

2.1 线程ID 的数据类型

2.1.1 进程ID的数据类型

  • 进程ID的数据类型为 pid_t
    进程在系统中唯一的标识。获取进程ID的函数为:getpid()

2.1.2 线程ID的数据类型

  • 线程ID的数据类型为 pthread_t 线程ID代表 线程所属进程中,线程的唯一标识。它只在所属进程有获取线程ID的函数 pthread_self();

注意:

  • 线程ID的底层为: typedef unsigned long int pthread_t;
  • 进程ID的底层类型为 int型。
  • 所以就Linux来说,打印线程ID可以直接打印%lu。

2.2 创建线程

2.2.1 函数原型

#include <pthread.h>
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
					void *(*start_routine) (void *), void *arg);
  • 一般在创建线程时,需要创建一个pthread_t 类型的变量,用来接受创建成功后的线程的线程ID。
  • 这个函数只是创建一个线程,线程的调度由操作系统的调度算法决定。

2.2.2 函数参数

  • thread
    指向pthread_t类型的指针,改地址将存放线程创建成功之后的线程ID。 所以在写程序的时候,需要定义一个 pthread_t 类型的变量,创建线程时将这个变量的指针传递过去。线程创建成功后,会将返回的线程id存储到这个变量中。

  • attr
    线程的属性,一般不需要特殊的设置,所以一般简单的置空NULL,使用缺省属性(默认属性)。

  • void * ( * start_routine) (void * )
    start_routine 函数指针,指向新线程所要执行的函数的地址。所指函数的函数原型为:只有一个参数 void* ,返回值也只有一个参数 void*

  • arg
    传递给新线程的参数( 需要传递给 新线程函数 的实参

注意1:

  • 标准线程创建接口只留了 一个参数传递。如果想给线程函数传递多个参数,该怎么解决呢?传递一个结构体便可以了。
  • pthread_create 只是创建一个线程,但是何时被调度由操作系统的调度算法决定。

注意2:

  • 创建结构时,如果使用一个结构指针,引用结构成员的话使用->符号。使用一个结构指针也可以这样引用结构中的成员(*结构指针).结构成员
  • 如果使用结构变量引用结构成员的话可以用引用符.

2.3 线程终止

2.3.1 函数原型

#include <pthread.h>
void pthread_exit(void *retval);    // retval 参数用于获取退出状态,也就是pthread_exit 执行后,会将执行状态填入retval指向的空间中

2.3.2 函数参数

  • retval
    指向 线程退出返回值(退出状态) 的指针 疑问点!!!
    注意:
  • retval 绝不能用它返回一个指向局部变量的指针,因为线程调用该函数后,这个局部变量就不存在了,这将引起严重的程序漏洞。 如果返回的话,将会得到一个随机值。
  • 只要主线程退出,其他线程也会终止。

2.3.3 retval可以返回的值(退出状态)

  • 全局变量
  • 静态变量
  • 代码段
  • 堆空间的内存

2.4 等待线程终止,回收线程退出状态

2.4.1 函数原型

#include <pthread.h>
int pthread_join(pthread_t thread, void **retval);
//为什么是个二级指针?			相当于进程中的wait函数

注意
一般此函数用在主线程中,等待通过thread指定的线程终止,此函数调用成功,
可以通过value_ptr获取终止线程的返回值。

2.4.2 函数参数

  • thread : 线程id
  • retval : 获取线程的返回值(获取退出状态)

2.4.3 函数返回值

  • 成功 0
  • 失败 返回错误码

注意:为什么参数是二级指针?

  • 线程退出时,返回的状态是一个指针,而我们在主线程中需要将这个指针分配一个空间给存起来。分配空间时,是由一个指针指向的。指针指向的空间中存的是指针,因此指针本身是二级指针。
  • 对比进程退出函数: 创建进程的函数并不会返回进程的状态,进程状态的返回需要借助一个函数,即ptread_exit函数,这个函数可以把在线程内部把线程的退出信息发送到主线程。而主线程需要用一段空间来存储这个子线程退出时候的状态,因此需要在主线程中提前定义一个变量 ,通过pthread_join函数,来接受到线程的退出状态。即将retval这个变量来接受这个信息即可,而retval自身是一个指针类型。而pthread_join的定义者将这个函数的参数设置成了一个二级指针,因此在主线程中应该定义一个一级指针,而将这个一级指针的地址传递给pthread_join函数,便可以获取线程的退出状态了。

2.5 取消线程

2.5.1 函数原型

#include <pthread.h>
int pthread_cancel(pthread_t thread);

请求取消同一进程中的另外一个线程。

2.5.2 函数参数:

  • thread 请求取消的 线程的ID

2.5.3返回值:

  • 成功 0
  • 失败 返回非0的数字

注意:
线程通过调用pthread_cancel来请求取消同一个进程中正在运行的其他线程。
如果一个线程被取消,那pthread_join接受的线程返回值为PTHREAD_CANCELED;
pthread_cancel并不等待线程终止,仅提出请求。
#define PTHREAD_CANCELED ((void *) -1)

posted @ 2020-03-28 16:39  江南又一春  阅读(418)  评论(0编辑  收藏  举报