0. Linux 线程编程常用函数汇总
函数 | 说明 | 参数 | 返回值 |
---|---|---|---|
pthread_create | 创建新线程 | - pthread_t *thread : 新线程的标识符 | - pthread_t : 成功,NULL : 失败 |
- const pthread_attr_t *attr : 线程属性,默认为NULL | |||
- void *(*start_routine)(void *) : 线程执行的函数 | |||
- void *arg : 传递给线程执行函数的参数 | |||
pthread_join | 主线程等待子线程结束 | - pthread_t thread : 目标线程的标识符 | - 成功:0,失败:错误代码 |
- void **value_ptr : 用于存储目标线程返回值的地址 | |||
pthread_exit | 线程结束并返回值 | - void *value_ptr : 线程的返回值 | 无 |
pthread_self | 获取当前线程ID | 无 | pthread_t : 当前线程的标识符 |
pthread_mutex_init | 初始化互斥锁 | - pthread_mutex_t *mutex : 互斥锁的指针 | - 成功:0,失败:错误代码 |
- const pthread_mutexattr_t *attr : 互斥锁属性,默认为NULL | |||
pthread_mutex_destroy | 销毁互斥锁 | - pthread_mutex_t *mutex : 互斥锁的指针 | - 成功:0,失败:错误代码 |
pthread_mutex_lock | 锁定互斥锁 | - pthread_mutex_t *mutex : 互斥锁的指针 | - 成功:0,失败:错误代码 |
pthread_mutex_unlock | 解锁互斥锁 | - pthread_mutex_t *mutex : 互斥锁的指针 | - 成功:0,失败:错误代码 |
pthread_cond_init | 初始化条件变量 | - pthread_cond_t *cond : 条件变量的指针 | - 成功:0,失败:错误代码 |
- const pthread_condattr_t *attr : 条件变量属性,默认为NULL | |||
pthread_cond_destroy | 销毁条件变量 | - pthread_cond_t *cond : 条件变量的指针 | - 成功:0,失败:错误代码 |
pthread_cond_wait | 等待条件变量 | - pthread_cond_t *cond : 条件变量的指针 | - 成功:0,失败:错误代码 |
- pthread_mutex_t *mutex : 与条件变量相关联的互斥锁的指针 | |||
pthread_cond_signal | 唤醒等待条件变量的一个线程 | - pthread_cond_t *cond : 条件变量的指针 | - 成功:0,失败:错误代码 |
pthread_cond_broadcast | 唤醒等待条件变量的所有线程 | - pthread_cond_t *cond : 条件变量的指针 | - 成功:0,失败:错误代码 |
pthread_rwlock_init | 初始化读写锁 | - pthread_rwlock_t *rwlock : 读写锁的指针 | - 成功:0,失败:错误代码 |
- const pthread_rwlockattr_t *attr : 读写锁属性,默认为NULL | |||
pthread_rwlock_destroy | 销毁读写锁 | - pthread_rwlock_t *rwlock : 读写锁的指针 | - 成功:0,失败:错误代码 |
pthread_rwlock_rdlock | 读锁定读写锁 | - pthread_rwlock_t *rwlock : 读写锁的指针 | - 成功:0,失败:错误代码 |
pthread_rwlock_wrlock | 写锁定读写锁 | - pthread_rwlock_t *rwlock : 读写锁的指针 | - 成功:0,失败:错误代码 |
pthread_rwlock_unlock | 解锁读写锁 | - pthread_rwlock_t *rwlock : 读写锁的指针 | - 成功:0,失败:错误代码 |
1. 简介
-
1.1 什么是线程
- 线程是操作系统调度的最小执行单位,是进程的一部分,共享进程的资源。线程间通过共享内存进行通信。
- 示例代码:
#include <pthread.h> #include <stdio.h> void *thread_function(void *arg) { // 线程执行的函数体 return NULL; } int main() { pthread_t my_thread; pthread_create(&my_thread, NULL, thread_function, NULL); // 主线程继续执行其他任务 pthread_join(my_thread, NULL); // 等待线程结束 return 0; }
-
1.2 多线程的优势
- 提高程序并发性,充分利用多核处理器的性能。
- 适用于I/O密集型任务,避免阻塞整个进程。
-
1.3 线程与进程的区别
- 进程是独立的执行单元,有独立的地址空间和资源,进程间通信较为复杂。
- 线程是进程的子任务,共享进程的地址空间和资源,通过共享内存等机制进行通信。
2. 基础概念
- 2.1 线程的创建和终止
// 示例代码 #include <pthread.h> #include <stdio.h> void *thread_function(void *arg) { // 线程执行的函数体 return NULL; } int main() { pthread_t my_thread; pthread_create(&my_thread, NULL, thread_function, NULL); // 主线程继续执行其他任务 pthread_join(my_thread, NULL); // 等待线程结束 return 0; }
- 2.2 互斥锁和条件变量
// 示例代码 #include <pthread.h> #include <stdio.h> pthread_mutex_t my_mutex = PTHREAD_MUTEX_INITIALIZER; pthread_cond_t my_condition = PTHREAD_COND_INITIALIZER; void *thread_function(void *arg) { pthread_mutex_lock(&my_mutex); // 线程执行的任务 pthread_cond_signal(&my_condition); pthread_mutex_unlock(&my_mutex); return NULL; } int main() { pthread_t my_thread; pthread_create(&my_thread, NULL, thread_function, NULL); pthread_mutex_lock(&my_mutex); // 主线程等待条件变量 pthread_cond_wait(&my_condition, &my_mutex); pthread_mutex_unlock(&my_mutex); return 0; }
3. 进阶主题
-
3.1 线程同步
-
3.1.1 信号量
- 信号量是一种用于线程同步的机制,通过计数器来控制对资源的访问。
- 示例代码:
#include <pthread.h> #include <semaphore.h> #include <stdio.h> sem_t my_semaphore; void *thread_function(void *arg) { sem_wait(&my_semaphore); // 等待信号量 // 线程执行的任务 sem_post(&my_semaphore); // 释放信号量 return NULL; } int main() { sem_init(&my_semaphore, 0, 1); // 初始化信号量 pthread_t my_thread; pthread_create(&my_thread, NULL, thread_function, NULL); // 主线程继续执行其他任务 pthread_join(my_thread, NULL); // 等待线程结束 sem_destroy(&my_semaphore); // 销毁信号量 return 0; }
-
3.1.2 屏障
- 屏障用于协调多个线程的执行,在所有线程都到达屏障点时,才能继续执行。
- 示例代码:
#include <pthread.h> #include <stdio.h> pthread_barrier_t my_barrier; void *thread_function(void *arg) { // 线程执行的任务 pthread_barrier_wait(&my_barrier); // 等待其他线程到达屏障点 // 屏障后继续执行任务 return NULL; } int main() { pthread_barrier_init(&my_barrier, NULL, NUM_THREADS); // 初始化屏障 pthread_t my_thread[NUM_THREADS]; for (int i = 0; i < NUM_THREADS; ++i) { pthread_create(&my_thread[i], NULL, thread_function, NULL); } // 主线程继续执行其他任务 for (int i = 0; i < NUM_THREADS; ++i) { pthread_join(my_thread[i], NULL); // 等待线程结束 } pthread_barrier_destroy(&my_barrier); // 销毁屏障 return 0; }
-
-
3.2 线程池的实现
// 示例代码 #include <pthread.h> #include <stdio.h> #define THREAD_POOL_SIZE 5 pthread_t thread_pool[THREAD_POOL_SIZE]; void *thread_function(void *arg) { // 线程池中线程的执行函数 return NULL; } int main() { for (int i = 0; i < THREAD_POOL_SIZE; ++i) { pthread_create(&thread_pool[i], NULL, thread_function, NULL); } // 主线程继续执行其他任务 for (int i = 0; i < THREAD_POOL_SIZE; ++i) { pthread_join(thread_pool[i], NULL); // 等待线程结束 } return 0; }
4. 调试与性能优化
-
4.1 GDB调试多线程程序
- GDB是GNU调试器,用于调试程序。在调试多线程程序时,可以使用以下命令行进行调试:
gdb ./your_program (gdb) target exec ./your_program (gdb) break your_breakpoint (gdb) run (gdb) thread apply all bt
break
:设置断点run
:运行程序thread apply all bt
:打印所有线程的调用堆栈
- GDB是GNU调试器,用于调试程序。在调试多线程程序时,可以使用以下命令行进行调试:
-
4.2 线程安全性和性能优化技巧
-
线程安全性:
- 使用互斥锁(Mutex)来保护共享资源,避免多线程同时访问导致数据不一致。
- 注意避免死锁,使用适当的加锁顺序。
- 使用条件变量(Condition Variable)实现线程间的协同操作。
-
性能优化技巧:
- 减小锁的粒度,尽量缩小临界区的范围。
- 使用读写锁(Read-Write Lock)实现读写分离,提高并发性能。
- 考虑使用无锁数据结构,如原子操作等,减小锁的开销。
- 合理使用线程池来管理线程,减少线程创建销毁的开销。
- 使用性能分析工具,如
perf
等,定位性能瓶颈并进行优化。
// 示例代码:使用读写锁进行读写分离 #include <pthread.h> #include <stdio.h> pthread_rwlock_t my_rwlock; void *read_thread(void *arg) { pthread_rwlock_rdlock(&my_rwlock); // 读操作 pthread_rwlock_unlock(&my_rwlock); return NULL; } void *write_thread(void *arg) { pthread_rwlock_wrlock(&my_rwlock); // 写操作 pthread_rwlock_unlock(&my_rwlock); return NULL; } int main() { pthread_rwlock_init(&my_rwlock, NULL); // 初始化读写锁 // 创建读线程和写线程 pthread_rwlock_destroy(&my_rwlock); // 销毁读写锁 return 0; }
-
5. 实际应用与案例分析
-
5.1 多线程网络编程*(这里看不懂没关系,网络编程后面还会详细讲到)*
- 在多线程网络编程中,可以利用多线程处理并发的网络请求,提高服务器的响应能力。使用线程池管理线程,避免频繁创建销毁线程的开销。
- 示例代码:
#include <pthread.h> #include <stdio.h> #define THREAD_POOL_SIZE 5 pthread_t thread_pool[THREAD_POOL_SIZE]; void *thread_function(void *arg) { // 网络请求处理任务 return NULL; } int main() { for (int i = 0; i < THREAD_POOL_SIZE; ++i) { pthread_create(&thread_pool[i], NULL, thread_function, NULL); } // 主线程继续执行其他任务 for (int i = 0; i < THREAD_POOL_SIZE; ++i) { pthread_join(thread_pool[i], NULL); // 等待线程结束 } return 0; }
-
5.2 并行算法与数据结构
- 并行排序算法示例:
#include <pthread.h> #include <stdio.h> #include <stdlib.h> #define ARRAY_SIZE 1000000 #define NUM_THREADS 4 int array[ARRAY_SIZE]; typedef struct { int start; int end; } ThreadData; void *parallel_merge_sort(void *arg) { ThreadData *data = (ThreadData *)arg; // 在[start, end]范围内进行归并排序 return NULL; } int main() { // 初始化数组 pthread_t threads[NUM_THREADS]; ThreadData thread_data[NUM_THREADS]; // 划分数组,每个线程处理一部分 for (int i = 0; i < NUM_THREADS; ++i) { pthread_create(&threads[i], NULL, parallel_merge_sort, &thread_data[i]); } // 主线程等待所有线程结束 for (int i = 0; i < NUM_THREADS; ++i) { pthread_join(threads[i], NULL); } // 合并排序结果 return 0; }
- 并行排序算法示例:
-
5.3 实际案例分析与解决方案
- 示例代码:(假设存在一个需要解决的线程安全问题)
#include <pthread.h> #include <stdio.h> int shared_variable = 0; pthread_mutex_t my_mutex = PTHREAD_MUTEX_INITIALIZER; void *thread_function(void *arg) { for (int i = 0; i < 100000; ++i) { pthread_mutex_lock(&my_mutex); // 线程执行可能存在的竞态条件操作 shared_variable++; pthread_mutex_unlock(&my_mutex); } return NULL; } int main() { pthread_t my_thread1, my_thread2; pthread_create(&my_thread1, NULL, thread_function, NULL); pthread_create(&my_thread2, NULL, thread_function, NULL); pthread_join(my_thread1, NULL); pthread_join(my_thread2, NULL); printf("Final value of shared_variable: %d\n", shared_variable); return 0; }
- 示例代码:(假设存在一个需要解决的线程安全问题)
6. 参考资料
-
6.1 书籍推荐
- “UNIX网络编程” by W. Richard Stevens
- “Linux多线程服务端编程” by 陈硕
-
6.2 在线资源链接
-
6.3 开源项目示例
- Nginx: 一个高性能的HTTP和反向代理服务器,采用多线程模型处理并发请求。
- SQLite: 轻量级嵌入式数据库引擎,使用多线程处理数据库操作。
- Boost C++ Libraries: 提供了丰富的C++库,其中包括线程库(boost.thread)。
大家有任何不懂的都可以留言讨论,欢迎评论!