嵌入式第三十七篇——linux系统编程——线程控制

在多线程编程中,临界资源 (全局变量、文件、设备等会被多线程读写的资源)的访问控制是核心问题,主要通过互斥 和同步 机制解决,同时需规避死锁风险。

一、互斥

1. 概念

对临界资源的排他性访问,即同一时刻只能有一个线程对临界资源进行读写操作。

  • 问题根源 :多线程并发执行时,指令可能被穿插调度(如A++对应的汇编指令分 3 步执行),导致数据一致性破坏。
  • 核心目标:保证临界区代码(访问临界资源的代码)的原子性。

2. 互斥锁的使用步骤

定义 → 初始化 → 加锁 → 解锁 → 销毁

3. 相关函数(POSIX 标准)

操作 函数原型 功能说明
定义 pthread_mutex_t mutex; 声明互斥锁变量
初始化 int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr); 初始化互斥锁,attr为NULL表示默认属性;成功返回 0,失败返回非零
加锁 int pthread_mutex_lock(pthread_mutex_t *mutex); 对临界区加锁,若锁已被占用则线程阻塞;加锁后代码为原子操作(一次调度必完成);成功返回 0,失败返回非零
解锁 int pthread_mutex_unlock(pthread_mutex_t *mutex); 释放互斥锁,解锁后其他线程可竞争锁;成功返回 0,失败返回非零
销毁 int pthread_mutex_destroy(pthread_mutex_t *mutex); 销毁已初始化的互斥锁;成功返回 0,失败返回非零

4. 注意事项

  • 加锁和解锁必须由同一个线程执行。
  • 临界区代码需短小精悍,避免休眠、大耗时操作(否则会降低多线程效率)。

二、同步

1. 概念

线程按照特定先后顺序对临界资源进行排他性访问,是互斥的特例(互斥包含同步)。

实现方式 :常用信号量(计数信号量),可实现线程间的交叉释放(如线程 1 释放资源唤醒线程 2,线程 2 释放资源唤醒线程 1)。

2. 信号量的使用步骤

定义 → 初始化 → PV 操作 → 销毁

3. 相关函数

操作 函数原型 功能说明
定义 sem_t sem; 声明信号量变量
初始化 int sem_init(sem_t *sem, int pshared, unsigned int value); 初始化信号量:pshared=0为线程间使用,pshared≠0为进程间使用;value为信号量初始值(二值信号量常用 0/1,计数信号量可大于 1);成功返回 0,失败返回 - 1
P 操作(申请资源) int sem_wait(sem_t *sem); 判断信号量是否有资源:有资源(value≥1)则value-1并继续执行,无资源(value=0)则线程阻塞;成功返回 0,失败返回 - 1
V 操作(释放资源) int sem_post(sem_t *sem); 释放资源,value+1,线程不会阻塞;成功返回 0,失败返回 - 1
销毁 int sem_destroy(sem_t *sem); 销毁已初始化的信号量;成功返回 0,失败返回 - 1

4. 注意事项

  • 信号量允许临界区有短暂休眠或小耗时操作(相较于互斥锁更灵活)。
  • 二值信号量(value=0/1)用于单一资源的同步,计数信号量(value>1)用于多份资源的互斥访问。

三、死锁

1. 概念

因锁资源的申请 / 释放逻辑不合理,导致线程 / 进程无法正常执行的现象。

2. 产生死锁的四个必要条件(缺一不可)

(1)互斥条件:一个资源每次只能被一个线程 / 进程使用。

(2)请求与保持条件:线程 / 进程因请求资源阻塞时,对已获得的资源保持不放。

(3)不剥夺条件:线程 / 进程已获得的资源,在未使用完之前不能被强行剥夺。

(4)循环等待条件:若干线程 / 进程形成头尾相接的循环等待资源关系。

相关推荐
HideF3 小时前
Linux sudo
linux
FlightYe3 小时前
视界原理之3D视频(四):裸眼、眼镜和头显
android·linux·c++·3d·ffmpeg·音视频
蹊黎4 小时前
Linux 下用 C 语言实现进度条
linux·c语言·单片机
视觉小萌新5 小时前
AI Class 3 · Chapter 1:变量、字符串、list/dict、if/for(python学习-小白版-有经验可跳过)
python·学习·list
牛马鸡niumasi6 小时前
【Linux】C语言文件操作
linux
say_fall6 小时前
【Linux系统编程】Ext 文件系统:磁盘与存储、文件与目录、现代计算机究竟如何寻找文件
linux·运维·服务器·数据库·c++
wacsii6 小时前
【Linux进程(一)】Linux 进程初探:操作系统如何管理进程?fork() 为什么返回两次?
linux·运维·服务器
AI+程序员在路上7 小时前
RV1126B 上支持的模型及全流程应用--从CNN及语音到 LLMVLM 与跨平台选型
linux·c语言·人工智能
默|笙7 小时前
【Linux网络】传输层协议TCP(1)---TCP报文介绍
linux·网络·tcp/ip
相思难忘成疾7 小时前
从零搭建 Kubernetes 1.30 集群:kubeadm 部署一主多从实战(RHEL 9.3 + Docker + flannel)
linux·运维·kubernetes