Linux 线程间通信

一、线程间通信的实现方式

1. 共享空间通信

一个进程内部的所有线程共享数据段和堆区,因此全局变量、静态变量、堆区空间都是共享的,可以利用这些空间进行通信。

2. 资源竞争问题

多线程操作全局变量空间时,会引入资源竞争,导致数据不一致。

3. 避免资源竞争的方法

多线程要避免引入资源竞争,可以通过加互斥锁解决。

4. 最简单的通信方式

线程间通信最简单的方法:全局变量 + 锁。


二、原子操作

原子操作是指不会被 CPU 任务调度打断的一次最小的操作。它保证了操作的完整性,是实现线程安全的基础。


三、互斥锁(Mutex)

1. 核心作用

避免多线程资源竞争,配合资源使用:

  • 使用资源前加锁
  • 使用资源结束后解锁

⚠️ 注意:加锁后,无法再次加锁,必须等到解锁后才能继续加锁。

2. 临界代码与临界区

  • 临界代码 / 临界区:加锁解锁中间的代码称为临界代码或临界区。
  • 执行规则:临界代码或临界区不可能同时被 CPU 任务执行,保证了同一时间只有一个线程访问共享资源。

3. 互斥锁函数接口

1. pthread_mutex_init
复制代码
int pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restrict attr);
  • 功能:互斥锁的初始化
  • 参数 :
    • mutex:互斥锁空间首地址
    • attr:互斥锁的属性,默认传 NULL
  • 返回值:成功返回 0,失败返回非 0
2. pthread_mutex_destroy
复制代码
int pthread_mutex_destroy(pthread_mutex_t *mutex);
  • 功能:互斥锁的销毁
  • 参数 :mutex:互斥锁空间首地址
3. pthread_mutex_lock
复制代码
int pthread_mutex_lock(pthread_mutex_t *mutex);
  • 功能:互斥锁加锁
  • 参数 :mutex:互斥锁空间首地址
4. pthread_mutex_unlock
复制代码
int pthread_mutex_unlock(pthread_mutex_t *mutex);
  • 功能:互斥锁解锁
  • 参数 :mutex:互斥锁空间首地址
5. pthread_mutex_trylock
  • 用 pthread_mutex_trylock 替代 pthread_mutex_lock,如果无法加锁则成功完成异常处理流程,防止程序卡死。
  • 加锁顺序保持一致,可有效预防死锁。

四、死锁

1. 定义

多任务通信过程中,由于加锁导致多个任务均无法向下执行的状态称为死锁。

2. 死锁产生的 4 个必要条件

  • 互斥条件:资源是独占的,一个资源每次只能被一个线程使用。
  • 不可剥夺条件:线程已获得的资源,在未使用完之前,不能被强行剥夺。
  • 请求保持:线程已经保持了至少一个资源,又提出了新的资源请求。
  • 循环等待:若干线程之间形成一种头尾相接的循环等待资源关系。

五、信号量(Semaphore)

1. 核心作用

信号量可以实现多线程间的同步,让多个任务具有先后顺序关系。

  • 同步:拥有严格的先后执行的逻辑顺序关系。
  • 异步:代码执行流程没有任何关联性。

2. 信号量的本质

信号量是一个资源,可以初始化、销毁、申请和释放:

  • 如果资源数 > 0,则申请资源是让资源数 -1。
  • 如果资源数为 0,申请资源时则会阻塞等待,等待有人释放资源,才能申请拿到资源。
  • 释放不会阻塞,让资源数 +1。

3. 信号量的函数接口

1. sem_init
复制代码
int sem_init(sem_t *sem, int pshared, unsigned int value);
  • 功能:对信号量初始化
  • 参数 :
    • sem:信号量空间首地址
    • pshared:信号量的作用域
      • 0:线程共享
      • 非0:进程间共享
    • value:信号量的初始值
  • 返回值:成功返回 0,失败返回非 0
2. sem_destroy
复制代码
int sem_destroy(sem_t *sem);
  • 功能:销毁无名信号量
  • 参数 :sem:信号量空间首地址
3. sem_wait
复制代码
int sem_wait(sem_t *sem);
  • 功能:申请资源,让资源数 -1。如果资源数为 0,则阻塞等待。
  • 参数 :sem:信号量空间首地址
4. sem_post
复制代码
int sem_post(sem_t *sem);
  • 功能:释放资源,让资源数 +1。
  • 参数 :sem:信号量空间首地址
相关推荐
草莓熊Lotso1 小时前
【C++ 基于微服务的即时通讯系统】etcd + brpc 从安装到服务注册发现全链路实战
网络·数据库·c++·redis·微服务·etcd
Lethehong6 小时前
Oracle 加个字段,目标库就报错?KFS 用“先拆后组“打通异构 DDL
数据库·oracle
HPtiger7 小时前
数据结构——选择排序
数据结构·算法·排序算法
Web极客码7 小时前
锁定真正的磁盘卡顿:我用 OpenCode 配合 eBPF 诊断 NVMe 队列深度延迟与 I/O 写放大
数据库·oracle
康实训7 小时前
老年评估仿真实训平台架构设计与老年人能力评估实训室教学落地实践
大数据·人工智能·算法·实训室·实训室建设
DongQiShanRen7 小时前
六根硬件映射(四):归属澄清、两处不一致与卷十一总表
开发语言·人工智能·算法·rust·哈希算法·集成学习
CCblandy7 小时前
雪花 ID 四个边界实测:时钟回拨重号 500 个,前端 JSON.parse 直接丢精度
后端·python·算法·性能优化·架构
cspttty7 小时前
2027用户研究求职准备:应用统计学如何补齐研究设计与业务表达
大数据·数据库
丑梨数据7 小时前
信创环境里跑文档工具:格式兼容与本地合规的几个坑
数据结构·人工智能·算法·决策树·排序算法
roman_日积跬步-终至千里8 小时前
【数据Agent论文·查询与语义|05】Spider:为什么换一个数据库,模型就不会查了?
数据库·数据分析