操作线程的函数
- 线程的创建
1 | # include <pthread.h> |
参数 | 说明 |
---|---|
thread | 输出参数,由 pthread_create 在线程创建成功后返回的线程句柄,该句柄在后续操作线程的 API 中用于标志该新建的线程; |
start_routine | 输入参数,新建线程的入口函数; |
arg | 输入参数,传递给新线程入口函数的参数; |
attr | 输入参数,指定新建线程的属性,如线程栈大小等;如果值为 NULL,表示使用系统默认属性。 |
- 线程ID
1 | include <pthread.h> |
- 判断两个给定的线程ID是否相等
1 | include <pthread.h> |
参数 | 说明 |
---|---|
t1 | 线程ID t1 |
t2 | 线程ID t2 |
- 线程的终止
1 | include <pthread.h> |
参数 | 说明 |
---|---|
retval | 输出参数,等待的线程终止时的返回值 |
- 线程的连接
1 | include <pthread.h> |
参数 | 说明 |
---|---|
thread | 输入参数,指定希望等待的线程 |
retval | 输出参数,等待的线程终止时的返回值,就是在线程入口函数中 return 的值或者调用 pthread_exit 函数的参数 |
- 线程的分离
1 | # include <pthread.h> |
参数 | 说明 |
---|---|
thread | 输入参数,指定希望执行分离操作的线程 |
线程的属性
- 属性的初始化与销毁
1 | # include <pthread.h> |
- 获取指定线程的属性
1 | # define _GNU_SOURCE |
- 设置和获取线程的分离状态
1 | # include <pthread.h> |
- 设置和获取线程栈地址及大小
1 | # include <pthread.h> |
线程的一次性初始化及特有数据
场景:我们同时创建了N个线程,无法知道哪个线程会被先执行。我们期望这N个线程中谁先运行谁就要去负责去调用一个全局的初始化函数做相关的初始化动作,而该初始化函数仅能被调用一次。
- 一次性初始化线程
1 | # include <pthread.h> |
参数 | 说明 |
---|---|
once_control | 输入参数,指针,指向通过以下方式初始化的全局变量 pthread_once_t once_var = PTHREAD_ONCE_INIT; |
init | 输入参数,函数指针,执行仅能被执行一次的初始化函数 |
- 线程特有数据
1 | # include <pthread.h> |
参数 | 说明 |
---|---|
pthread_key_create | 创建一个全局唯一的 key,用于表示一个数据概念 |
pthread_setspecific | 用于线程给某个数据概念分配内存 |
pthread_getspecific | 用于线程针对某个数据概念获取其对应的内存(每个线程获取的内存是不一样的),如果函数返回 NULL 值说明线程还未对该数据概念分配内存 |
- 创建 mystrerror.c,代码如下:
1 | # define _GNU_SOURCE |
线程的取消
场景:一个线程可以对另一个线程提出取消申请,即线程被动终止的一种情况。
1 | # include <pthread.h> |
- 创建 thread_cancel_sample.c,代码如下:
1 | /* |
线程互斥
场景:当有多个线程并发的在临界区执行时,程序的执行结果会出现不确定性,这种情况称之为竞态条件。多线程编程中,避免出现竞态条件的一项重要解决方案就是,保证多个线程在临界区是互斥的。所谓的互斥,就是指不能同时有多于一个线程进入临界区。保证临界区互斥的重要技术,就是互斥锁。
- 互斥锁
1 | # 静态初始化一个全局的互斥锁 |
- 创建 thread_sync_sample.c,代码如下:
1 | /* |
线程同步
场景:我们有一个共享内存数据资源 M,我们整个程序设计需求是要求线程 A 在 M 上做了处理之后,线程 B 才能做处理。这种需要确保多线程间执行先后顺序的技术,称为线程的同步。条件变量是线程同步的主要手段。其大致的实现思想就是:线程 B,调用条件变量的接口让自身阻塞;线程 A,在处理完资源后,通过条件变量接口唤醒正在等待该资源的线程 B。
- 条件变量
1 | # 静态初始化:与互斥锁类似静态初始化一个全局的条件变量 |
- 创建 pthread_cond_sample.c,代码如下:
1 | # include <stdio.h> |