当前位置:首页>Linux>Linux系统开发 多线程 知识点大纲

Linux系统开发 多线程 知识点大纲

  • 2026-10-11 06:14:21
Linux系统开发 多线程 知识点大纲

一、多线程基础概念

1.1 进程与线程的区别

对比项
进程
线程
内存空间
独立地址空间
共享进程地址空间
资源开销
创建/切换开销大
创建/切换开销小
通信方式
需要IPC机制
直接共享内存
独立性
进程崩溃不影响其他进程
线程崩溃可能导致整个进程崩溃
调度单位
资源分配的基本单位
CPU调度的基本单位

1.2 多线程的优点

  • 提高程序响应速度
  • 提高资源利用率(CPU、内存等)
  • 实现任务的并行处理
  • 适合I/O密集型与计算密集型任务

1.3 多线程的适用场景

  • 高并发服务器处理
  • 大文件断点续传
  • 多文件同时读写操作
  • 实时数据处理
  • 嵌入式设备多任务并行

二、POSIX线程标准与库

2.1 遵循标准

  • POSIX线程接口标准(pthread)
  • 由IEEE和ISO制定
  • 提供跨平台兼容性

2.2 头文件与编译

#include<pthread.h>

编译链接选项:-lpthread


三、线程的生命周期

状态
说明
新建(New)
线程刚被创建,尚未启动
就绪(Ready)
线程已准备好,等待CPU调度
运行(Running)
线程正在执行
阻塞(Blocked)
线程等待某条件(I/O、锁、信号量等)
终止(Terminated)
线程执行完毕或被取消

3.1 状态转换关系

新建 → 就绪 → 运行 → 终止           ↓     ↑          阻塞 ←┘

四、线程的基本操作

4.1 线程创建

函数原型:

intpthread_create(pthread_t *thread,constpthread_attr_t *attr,void *(*start_routine)(void*),void *arg);
参数
说明
thread
指向线程ID的指针,创建成功后填充
attr
线程属性,NULL表示默认属性
start_routine
线程入口函数
arg
传递给入口函数的参数

返回值: 0表示成功,非0表示错误码

4.2 线程等待(Join)

函数原型:

intpthread_join(pthread_t thread, void **retval);
参数
说明
thread
要等待的线程ID
retval
接收线程返回值的指针,NULL表示不关心

作用: 阻塞调用线程,直到指定线程结束

4.3 线程分离(Detach)

函数原型:

intpthread_detach(pthread_t thread);
特性
pthread_joinpthread_detach
主线程行为
阻塞等待子线程结束
不等待,子线程独立运行
资源回收
子线程结束后由join回收
子线程结束后自动回收
返回值获取
可以获取
无法获取
使用场景
需要知道子线程结果
子线程独立运行,无需关心结果

4.4 线程退出

退出方式
函数/方法
说明
自然退出
return
线程函数执行完毕
主动退出
pthread_exit(void *retval)
线程主动调用退出
被取消
pthread_cancel(pthread_t thread)
其他线程取消该线程
随进程退出
进程终止
所有线程随之终止

pthread_exit函数原型:

voidpthread_exit(void *retval);

4.5 线程取消

函数原型:

intpthread_cancel(pthread_t thread);

取消点: 线程在执行某些函数时会检查取消请求,如read()、write()、sleep()等

4.6 线程清理(Cleanup)

注册清理函数:

voidpthread_cleanup_push(void (*routine)(void*), void *arg);voidpthread_cleanup_pop(int execute);
参数
说明
routine
清理函数指针
arg
传递给清理函数的参数
execute
非0时执行清理函数,0时不执行

使用场景: 线程被取消或调用pthread_exit时,执行资源释放等清理工作

4.7 获取线程ID

函数原型:

pthread_tpthread_self(void);

作用: 返回调用线程的线程标识符


五、线程属性操作

5.1 属性初始化与销毁

intpthread_attr_init(pthread_attr_t *attr);intpthread_attr_destroy(pthread_attr_t *attr);

5.2 分离属性(Detach State)

intpthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate);intpthread_attr_getdetachstate(constpthread_attr_t *attr, int *detachstate);
属性值
说明
PTHREAD_CREATE_JOINABLE
可连接(默认)
PTHREAD_CREATE_DETACHED
分离状态

5.3 栈大小属性(Stack Size)

intpthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize);intpthread_attr_getstacksize(constpthread_attr_t *attr, size_t *stacksize);

作用: 设置/获取线程栈的大小,防止栈溢出或优化内存使用

5.4 调度属性

5.4.1 设置/获取调度参数

intpthread_setschedparam(pthread_t thread, int policy, const struct sched_param *param);intpthread_getschedparam(pthread_t thread, int *policy, struct sched_param *param);
调度策略
说明
SCHED_FIFO
先进先出实时调度
SCHED_RR
时间片轮转实时调度
SCHED_OTHER
默认分时调度

sched_param结构体:

structsched_param {int sched_priority;  // 调度优先级};

5.5 绑定属性(Contention Scope)

intpthread_attr_setscope(pthread_attr_t *attr, int scope);intpthread_attr_getscope(constpthread_attr_t *attr, int *scope);
属性值
说明
PTHREAD_SCOPE_SYSTEM
绑定(系统级竞争,与所有进程线程竞争CPU)
PTHREAD_SCOPE_PROCESS
非绑定(进程级竞争,只与同一进程线程竞争)

六、线程同步机制

6.1 互斥锁(Mutex)

6.1.1 互斥锁的基本概念

  • 保证同一时间只有一个线程访问临界区
  • 防止数据竞争(Race Condition)

6.1.2 互斥锁操作函数

函数
原型
作用
初始化
int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr)
初始化互斥锁
销毁
int pthread_mutex_destroy(pthread_mutex_t *mutex)
销毁互斥锁
加锁
int pthread_mutex_lock(pthread_mutex_t *mutex)
阻塞加锁
尝试加锁
int pthread_mutex_trylock(pthread_mutex_t *mutex)
非阻塞尝试加锁,失败立即返回
解锁
int pthread_mutex_unlock(pthread_mutex_t *mutex)
释放互斥锁

6.1.3 互斥锁使用步骤

定义锁 → 初始化锁 → 加锁 → 访问临界区 → 解锁 → 销毁锁

6.1.4 锁的粒度

类型
说明
优缺点
粗粒度锁
锁的范围大,保护多个资源
实现简单,但并发度低
细粒度锁
锁的范围小,保护单个资源
并发度高,但实现复杂,易死锁

6.1.5 互斥锁使用示例

#include<pthread.h>#include<stdio.h>pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;int counter = 0;void* increment(void* arg){    pthread_mutex_lock(&mutex);      // 加锁for (int i = 0; i < 10000; i++) {        counter++;    }    pthread_mutex_unlock(&mutex);    // 解锁returnNULL;}intmain(){pthread_t t1, t2;    pthread_create(&t1, NULL, increment, NULL);    pthread_create(&t2, NULL, increment, NULL);    pthread_join(t1, NULL);    pthread_join(t2, NULL);printf("Final counter: %d\n", counter);    pthread_mutex_destroy(&mutex);return0;}

6.2 条件变量(Condition Variable)

6.2.1 基本概念

  • 用于线程间的等待/通知机制
  • 必须与互斥锁配合使用

6.2.2 条件变量操作函数

函数
原型
作用
初始化
int pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *attr)
初始化条件变量
销毁
int pthread_cond_destroy(pthread_cond_t *cond)
销毁条件变量
等待
int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
阻塞等待条件满足
限时等待
int pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, const struct timespec *abstime)
限时阻塞等待
唤醒一个
int pthread_cond_signal(pthread_cond_t *cond)
唤醒一个等待线程
唤醒所有
int pthread_cond_broadcast(pthread_cond_t *cond)
唤醒所有等待线程

6.2.3 pthread_cond_wait的内部机制

  1. 释放互斥锁
  2. 阻塞等待条件变量
  3. 被唤醒后重新获取互斥锁

6.2.4 signal与broadcast的区别

函数
唤醒数量
使用场景
pthread_cond_signal
一个线程
只需一个线程处理任务,如线程池
pthread_cond_broadcast
所有等待线程
多个线程都需要响应,如状态变更通知

6.2.5 条件变量使用步骤

初始化条件变量和互斥锁    ↓线程A:加锁 → 检查条件 → 条件不满足 → cond_wait等待    ↓线程B:加锁 → 修改条件 → cond_signal/broadcast通知 → 解锁    ↓线程A被唤醒 → 重新加锁 → 继续执行 → 解锁    ↓销毁条件变量和互斥锁

6.3 信号量(Semaphore)

6.3.1 基本概念

  • 计数器,控制同时访问共享资源的线程数量
  • 允许多个线程同时访问(取决于初始值)

6.3.2 信号量操作函数

函数
原型
作用
初始化
int sem_init(sem_t *sem, int pshared, unsigned int value)
初始化信号量
等待(P操作)
int sem_wait(sem_t *sem)
信号量减1,为0时阻塞
尝试等待
int sem_trywait(sem_t *sem)
非阻塞尝试减1
发布(V操作)
int sem_post(sem_t *sem)
信号量加1,唤醒等待线程
获取值
int sem_getvalue(sem_t *sem, int *sval)
获取当前信号量值
销毁
int sem_destroy(sem_t *sem)
销毁信号量

sem_init参数说明:

参数
说明
sem
信号量指针
pshared
0表示线程间共享,非0表示进程间共享
value
信号量初始值

6.3.3 信号量使用步骤

初始化信号量(设置初始值)    ↓sem_wait获取信号量(P操作)    ↓访问共享资源    ↓sem_post释放信号量(V操作)    ↓销毁信号量

6.3.4 用信号量实现互斥

#include<pthread.h>#include<semaphore.h>#include<stdio.h>sem_t mutex;int counter = 0;void* increment(void* arg){    sem_wait(&mutex);        // P操作,获取信号量    counter++;printf("Counter: %d\n", counter);    sem_post(&mutex);        // V操作,释放信号量returnNULL;}intmain(){pthread_t t1, t2;    sem_init(&mutex, 0, 1);  // 初始值为1,实现互斥    pthread_create(&t1, NULL, increment, NULL);    pthread_create(&t2, NULL, increment, NULL);    pthread_join(t1, NULL);    pthread_join(t2, NULL);    sem_destroy(&mutex);return0;}

七、经典同步模型:生产者消费者模型

7.1 模型说明

  • 生产者线程:生成数据,放入缓冲区
  • 消费者线程:从缓冲区取出数据,消费
  • 缓冲区:有限大小的共享资源

7.2 同步要点

  • 缓冲区满时,生产者阻塞等待
  • 缓冲区空时,消费者阻塞等待
  • 互斥访问缓冲区

7.3 完整代码示例

#include<pthread.h>#include<stdio.h>#include<unistd.h>#define BUFFER_SIZE 5// 共享缓冲区int buffer[BUFFER_SIZE];int count = 0;      // 当前产品数量int in = 0;         // 生产者放入位置int out = 0;        // 消费者取出位置// 同步机制pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;pthread_cond_t not_full = PTHREAD_COND_INITIALIZER;   // 缓冲区不满pthread_cond_t not_empty = PTHREAD_COND_INITIALIZER;  // 缓冲区不空// 生产者函数voidproduce(int item){    pthread_mutex_lock(&mutex);// 缓冲区满,等待while (count == BUFFER_SIZE) {printf("Buffer full, producer waiting...\n");        pthread_cond_wait(&not_full, &mutex);    }// 放入产品    buffer[in] = item;    in = (in + 1) % BUFFER_SIZE;    count++;printf("Produced: %d, count=%d\n", item, count);// 通知消费者    pthread_cond_signal(&not_empty);    pthread_mutex_unlock(&mutex);}// 消费者函数intconsume(){    pthread_mutex_lock(&mutex);// 缓冲区空,等待while (count == 0) {printf("Buffer empty, consumer waiting...\n");        pthread_cond_wait(&not_empty, &mutex);    }// 取出产品int item = buffer[out];    out = (out + 1) % BUFFER_SIZE;    count--;printf("Consumed: %d, count=%d\n", item, count);// 通知生产者    pthread_cond_signal(&not_full);    pthread_mutex_unlock(&mutex);return item;}// 生产者线程void* producer_thread(void* arg){for (int i = 0; i < 10; i++) {        produce(i);        sleep(1);    }returnNULL;}// 消费者线程void* consumer_thread(void* arg){for (int i = 0; i < 10; i++) {        consume();        sleep(1);    }returnNULL;}intmain(){pthread_t prod, cons;    pthread_create(&prod, NULL, producer_thread, NULL);    pthread_create(&cons, NULL, consumer_thread, NULL);    pthread_join(prod, NULL);    pthread_join(cons, NULL);// 清理资源    pthread_mutex_destroy(&mutex);    pthread_cond_destroy(&not_full);    pthread_cond_destroy(&not_empty);return0;}

八、高级同步机制

8.1 读写锁(Read-Write Lock)

特性
说明
读锁
多个线程可同时获取读锁
写锁
独占,写时禁止其他读/写
适用场景
读多写少

函数原型:

intpthread_rwlock_init(pthread_rwlock_t *rwlock, constpthread_rwlockattr_t *attr);intpthread_rwlock_rdlock(pthread_rwlock_t *rwlock);      // 获取读锁intpthread_rwlock_wrlock(pthread_rwlock_t *rwlock);      // 获取写锁intpthread_rwlock_unlock(pthread_rwlock_t *rwlock);      // 释放锁intpthread_rwlock_destroy(pthread_rwlock_t *rwlock);

8.2 自旋锁(Spin Lock)

特性
说明
等待方式
忙等待(循环检测),不挂起线程
优点
锁持有时间短时,避免上下文切换开销
缺点
长时间等待会浪费CPU
适用场景
多核CPU、锁持有时间极短、临界区简单

函数原型:

intpthread_spin_init(pthread_spinlock_t *lock, int pshared);intpthread_spin_lock(pthread_spinlock_t *lock);intpthread_spin_trylock(pthread_spinlock_t *lock);intpthread_spin_unlock(pthread_spinlock_t *lock);intpthread_spin_destroy(pthread_spinlock_t *lock);

8.3 屏障(Barrier)

特性
说明
作用
等待所有线程到达某点后,再一起继续执行
适用场景
分阶段计算、并行算法同步

函数原型:

intpthread_barrier_init(pthread_barrier_t *barrier, constpthread_barrierattr_t *attr, unsignedint count);intpthread_barrier_wait(pthread_barrier_t *barrier);intpthread_barrier_destroy(pthread_barrier_t *barrier);

九、线程池

9.1 概念

  • 预先创建一组线程,等待分配任务
  • 任务提交到队列,线程从队列取任务执行

9.2 优点

  • 减少线程创建/销毁开销
  • 控制并发线程数量
  • 便于线程管理和资源控制

9.3 核心组件

组件
说明
工作线程
执行任务的线程
任务队列
存储待执行的任务
管理线程
动态调整线程数量(可选)

9.4 适用场景

  • 高并发服务器
  • 大量短小计算任务
  • 需要限制资源使用的场景

十、多线程常见问题与解决方案

10.1 竞态条件(Race Condition)

  • 原因:多个线程同时读写共享数据
  • 解决:使用互斥锁、原子操作等同步机制

10.2 死锁(Deadlock)

  • 原因:循环等待资源
  • 四个必要条件:互斥、占有等待、不可抢占、循环等待
  • 预防:按固定顺序加锁、超时机制、死锁检测

10.3 活锁(Livelock)

  • 原因:线程不断改变状态以响应对方,但无法继续执行
  • 解决:引入随机等待

10.4 饥饿(Starvation)

  • 原因:某些线程长期得不到资源
  • 解决:公平锁、优先级调整

十一、实际应用场景

11.1 大文件断点续传

  • 多线程分段下载/上传
  • 每个线程负责文件的一个部分
  • 使用互斥锁同步文件指针和进度信息

11.2 多文件同时读写

  • 线程池管理文件操作线程
  • 互斥锁保护共享日志或状态信息

11.3 高并发服务器

  • 线程池处理客户端连接
  • 条件变量/信号量控制连接数
  • 读写锁优化读多写少的配置数据访问

十二、多线程编程最佳实践

实践
说明
最小化锁粒度
只保护必要的临界区
避免长时间持有锁
减少线程阻塞时间
按固定顺序加锁
防止死锁
优先使用高级同步工具
如条件变量、信号量,而非忙等待
注意线程安全的数据结构
使用线程安全的库函数
正确处理线程退出
资源清理、避免僵尸线程
合理设置线程栈大小
避免栈溢出或内存浪费

最新文章

随机文章