C系列多线程编程API | Pthread库
前言
本文仅针对pthread库的使用做出必要 指导 ,并且居然较大的主观性。观看前默认阅读者已经知晓 进程、线程以及多线程的相关基础知识,具体可以参阅站内文章:
本文介绍的pthread是基于 POSIX 操作系统的多线程API,事实上,在C++11之后的标准库中已经集成了多线程库std::thread,但本文并未涉及。
POSIX 表示可移植操作系统接口 ( Portable Operating System Interface of UNIX,缩写为 POSIX )
目前主流的 Linux 和 Mac OS 都属于 POSIX 系统
值得注意的是,Windows系统并不是POSIX类型的操作系统,因此想要在windows系统上使用pthread需要安装相应的链接库。如果你没有这方面的困扰,就跳过该部分。
在Windows下配置pthread
快速使用
引用
基于
POSIX开发多线程程序需要加载<pthread.h>1
pthread提供了一个类型pthread_t用来表示一个线程pthread库不是Linux和Mac OS系统默认的库,编译连接时需要加上静态库libpthread.a,例如:1
g++ main.cpp -lpthread
VScode中配置链接库
待更
创建线程
pthread.h 提供了 pthread_create() 函数用于创建一个 POSIX 线程,并立即让它执行
1 | pthread_create (thread, attr, start_routine, arg) |
创建线程成功时,函数返回 0,若返回值不为 0 则说明创建线程失败
| 参数 | 描述 |
|---|---|
thread | 指向线程标识符指针 |
attr | 一个不透明的属性对象,用来设置线程属性 可以指定线程属性对象,也可以传递 NULL |
start_routine | 线程运行函数起始地址,一旦线程被创建就会执行 |
arg | 运行函数的参数,它必须通过把引用作为指针强制转换为 void 类型进行传递 如果没有传递参数,可以使用 NULL |
终止线程
pthread_exit() 函数可以用来显式地终止一个 POSIX 线程。通常情况下,pthread_exit() 函数是在线程完成工作后无需继续存在时被调用。
1 | pthread_exit (status) |
如果 main() 是在它所创建的线程之前结束,并通过 pthread_exit() 退出,那么其他线程将继续执行。否则,它们将在 main() 结束时自动被终止。
实例
1 |
|
传递参数
在上文中,我们了解到pthread_create()函数可以传入参数给线程函数,而线程函数如helloworld()可以传入void* args参数。
此外,可以见得:传入的参数被限定为void*类型,这是pthread的规定。
因此,综合以上几点我们可以利用C++的类型转换传递给线程函数几乎所有数据结构的参数,具体操作方式如下:
- 定义需要传递参数的结构体,并在
main()中创建实例; - 将实例的指针强制转换为
void*类型,作为参数传递给pthread_create(); - 在具体的线程函数中,将接受到的
args指针再强制转换为原来的结构体类型的指针从而进行数据还原。
实例
1 |
|
结果如下:
1 | g++ -g test.cpp -lpthread -o test |
连接与分离
待更
进程同步
互斥与同步机制基本函数
| 函数 | 说明 |
|---|---|
| pthread_mutex_init() | 互斥锁的初始化 |
| pthread_mutex_lock() | 锁定互斥锁,如果尝试锁定已经被上锁的互斥锁则阻塞至可用为止 |
| pthread_mutex_trylock() | 非阻塞的锁定互斥锁 |
| pthread_mutex_unlock() | 释放互斥锁 |
| pthread_mutex_destory() | 互斥锁销毁函数 |
信号量线程控制(默认无名信号量)
| 函数 | 说明 |
|---|---|
| sem_init(sem) | 初始化一个定位在sem的匿名信号量 |
| sem_wait() | 把信号量减1操作,如果信号量的当前值为0则进入阻塞,为原子操作 |
| sem_trywait() | 如果信号量的当前值为0则返回错误而不是阻塞调用(errno=EAGAIN),其实是sem_wait()的非阻塞版本 |
| sem_post() | 给信号量的值加1,它是一个“原子操作”,即同时对同一个信号量做加1,操作的两个线程是不会冲突的 |
| sem_getvalue(sval) | 把sem指向的信号量当前值放置在sval指向的整数上 |
| sem_destory(sem) | 销毁由sem指向的匿名信号量 |



