在上一篇文章中讲述了线程的概念和内存资源的分配,线程是一个很重要的知识,除了明白概念性的知识,了解其使用也是十分重要的。
与线程有关的函数构成了一个完整的系列,绝大多数函数的名字都是以 "pthread_" 打头的,使用它们所需要引入的头文件是<pthread.h>,而且链接时需要使用编译器命令的 "-lpthread"选项。
创建线程
创建一个线程要使用到的函数叫做 pthread_create。其原型为:
cpp
int pthread_create(pthread_t *restrict thread,
const pthread_attr_t *restrict attr,
void *(*start_routine)(void *),
void *restrict arg);
pthread_t *restrict thread输出参数,成功后存放新线程 ID。const pthread_attr_t *restrict attr线程属性配置,传NULL使用默认属性。void *(*start_routine)(void *)线程入口函数指针:接收void*,返回void*。void *restrict arg传递给线程入口函数的唯一参数。- 返回值:成功返回 0,失败返回错误码。
这里是一个简单的例子:
cpp
#include<unistd.h>
#include<stdlib.h>
#include<stdio.h>
#include<string.h>
#include<pthread.h>
#include<iostream>
void* routine(void* arg)
{
std::cout << "我是一个新线程" << std::endl;
sleep(1);
return nullptr;
}
int main()
{
pthread_t tid;
int ret = pthread_create(&tid,nullptr,routine,nullptr);
if(ret != 0)
{
perror("pthread_create failed");
return -1;
}
sleep(1);
std::cout << "我是主线程" << std::endl;
return 0;
}
在 Linux 下运行之后:

对比传统函数的:成功返回 0,失败返回 -1,并且对全局变量 error 赋值以示错误。pthread 函数没有使用这种方法,它不设置全局变量 error 而是将它直接返回,因为读取返回值要比读取线程内的 error 变量的开销要小。
TID获取
我们说过线程是轻量级进程,进程有一个标识其唯一性的东西叫做 PID ,线程同样也有,叫做 TID,上面代码中把线程ID设置为 tid 也是为了和这里对应起来。
在进程中,我们通过 getppid 和 getppid 来分别获取父子进程的 PID。而在线程中,没有父子之分,都是通过 函数 pthread_self 来获取线程的 TID 的。
函数原型:
cpp
pthread_t pthread_self(void);
可以看到这是一个无参的函数,返回值就是调用当前函数的线程ID。
例子:
我们直接在上面的那个例子最后打印这个函数的返回值,就可以得结果:

线程终止
终止线程的方法有很多种,回忆进程相关内容,我们可能想到用exit(),这当然可以终止线程,但是进程也会被终止掉,用 return 会导致相同的结果。
如果我们想要只终止当前线程,可以让那个线程调用 pthread_exit 终止自己。
cpp
void pthread_exit(void *retval);
retval:void*类型指针,代表线程退出返回值。
pthread_exit 是 "害己" 的,如果想要 "害人" ,可以使用 pthread_cancel 终止同一进程中的另一个线程。
cpp
int pthread_cancel(pthread_t thread);
thread:pthread_t类型,目标要取消的线程 ID (由pthread_create输出得到)。
线程等待
线程也需要像进程那样被等待,虽然没有进程那样的僵尸状态,但是会类似僵尸,导致内存泄漏,所以线程等待是十分必要的。
使用到的函数是 pthread_join:
原型:
cpp
int pthread_join(pthread_t thread, void **retval);
pthread_t thread是要等待的目标线程 ID,即pthread_create输出的线程标识。void **retval输出型二级指针,用于接收线程退出返回值。
使用这个函数时,线程不同的终止方式不同,retval 的内容会不同:

线程分离
默认情况下,新创建的线程是 joinable (可等待的),线程退出后,需要进行 pthread_join 等待,但如果我们不关心线程的返回值,join 反而成为了一种负担,我们可以告诉系统,当线程退出时,自动释放线程资源,这就是线程分离。
要实现线程分离,使用到的函数是 pthread_detach:
原型:
cpp
int pthread_detach(pthread_t thread);
参数就不需要解释了。