当前位置: 首页 > news >正文

嵌入式学习Day30

线程控制中互斥与同步:

概念:
互斥 ===》在多线程中对临界资源的排他性访问。
互斥机制 ===》互斥锁  ===》保证临界资源的访问控制。

Linux中的互斥锁

互斥锁(Mutex)是Linux中用于线程同步的基本机制,确保同一时间只有一个线程能访问共享资源。以下是Linux中互斥锁的使用方法和关键概念。

框架:
 定义互斥锁 ==》初始化锁 ==》加锁 ==》解锁 ==》销毁

互斥锁的初始化

在Linux中,互斥锁通过pthread_mutex_t类型表示。初始化方式分为静态初始化和动态初始化。

  • 静态初始化:直接使用宏PTHREAD_MUTEX_INITIALIZER
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

  • 动态初始化:通过pthread_mutex_init函数完成。
pthread_mutex_t mutex;
pthread_mutex_init(&mutex, NULL);

互斥锁的加锁与解锁
  • 加锁:使用pthread_mutex_lock函数,如果锁已被占用,线程会阻塞。用指定的互斥锁开始加锁代码,加锁后的代码到解锁部分的代码属于原子操作,在加锁期间其他进程/线程都不能操作该部分代码, 如果该函数在执行的时候,mutex已经被其他部分使用则代码阻塞。
pthread_mutex_lock(&mutex);
// 临界区代码
  • 非阻塞加锁:使用pthread_mutex_trylock,如果锁不可用,函数立即返回错误。
if (pthread_mutex_trylock(&mutex) == 0) {// 临界区代码
}
  • 解锁:使用pthread_mutex_unlock函数。将指定的互斥锁解锁。
      解锁之后代码不再排他访问,一般加锁解锁同时出现。
pthread_mutex_unlock(&mutex);

互斥锁的销毁

使用pthread_mutex_destroy函数释放互斥锁资源。

pthread_mutex_destroy(&mutex);

死锁的产生原因和产生的必要条件:

产生死锁的原因主要是:
(1) 因为系统资源不足。
(2) 进程运行推进的顺序不合适。
(3) 资源分配不当等。
如果系统资源充足,进程的资源请求都能够得到满足,死锁出现的可能性就很低,否则
就会因争夺有限的资源而陷入死锁。其次,进程运行推进顺序与速度不同,也可能产生死锁。
产生死锁的四个必要条件:
(1) 互斥条件:一个资源每次只能被一个进程使用。
(2) 请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放。
(3) 不剥夺条件:进程已获得的资源,在未使用完之前,不能强行剥夺。
(4) 循环等待条件:若干进程和线程之间形成一种头尾相接的循环等待资源关系。

线程同步的概念

线程同步是指在多线程环境中,通过特定机制协调线程的执行顺序,避免因并发访问共享资源导致的数据不一致或竞态条件。常见的同步机制包括互斥锁、信号量、条件变量等。

信号量概述

信号量(Semaphore)是Linux中用于进程或线程间同步的机制,由E.W. Dijkstra提出。它本质上是一个计数器,用于控制对共享资源的访问。信号量分为:

  • 二进制信号量:取值为0或1,类似互斥锁。
  • 计数信号量:取值为非负整数,用于限制资源数量。

sem_init函数概述

sem_init是Linux系统中用于初始化未命名信号量的函数,属于POSIX信号量 API(<semaphore.h>)。它常用于多线程或多进程间的同步控制,通过计数器机制管理资源访问。

函数原型

#include <semaphore.h>
int sem_init(sem_t *sem, int pshared, unsigned int value);

  • sem: 指向待初始化的信号量对象的指针。
  • pshared: 指定信号量的共享范围:
    • 0:信号量在线程间共享(同一进程内)。
    • 0:信号量在进程间共享(需放在共享内存中)。
  • value: 信号量的初始计数值(通常表示资源可用数量)。value 信号量的初始值,一般无名信号量, 都是二值信号量。
      0 表示红灯,进程暂停阻塞
      1 表示绿灯,进程可以通过执行

返回值

  • 成功:返回0
  • 失败:返回-1并设置errno(如EINVAL无效参数、ENOSPC资源耗尽)。

sem_t函数基本概念

sem_t 是一个不透明的结构体类型,通常通过指针操作。它分为两种类型:

  • 无名信号量:用于线程间同步,存储在共享内存中。
  • 有名信号量:用于进程间同步,通过文件系统路径名标识。

常用函数

以下是与 sem_t 相关的主要函数:

初始化信号量
int sem_init(sem_t *sem, int pshared, unsigned int value);
  • pshared0 表示线程间共享,非零表示进程间共享。
  • value:信号量初始值。
销毁信号量
int sem_destroy(sem_t *sem);
  • 仅用于无名信号量。

sem_wait 概述

sem_wait 是 Linux 系统中用于操作信号量(semaphore)的系统调用之一,属于 POSIX 线程(pthread)库的一部分。它的主要功能是尝试减少信号量的值,如果信号量的值大于零,则减一并立即返回;如果值为零,则调用线程会被阻塞,直到信号量的值变为非零。

功能:

判断当前sem信号量是否有资源可用。
  如果sem有资源(==1),则申请该资源,程序继续运行
  如果sem没有资源(==0),则线程阻塞等待,一 旦有资源
  则自动申请资源并继续运行程序。

  注意:sem 申请资源后会自动执行 sem = sem - 1;
参数:sem 要判断的信号量资源

函数原型

#include <semaphore.h>
int sem_wait(sem_t *sem);
  • 参数sem 是指向信号量对象的指针。
  • 返回值:成功时返回 0,失败时返回 -1 并设置 errno

使用场景

sem_wait 通常用于线程或进程间的同步,确保对共享资源的互斥访问。常见场景包括:

  • 控制临界区的进入(如共享内存、文件操作)。
  • 实现生产者-消费者模型中的资源计数。
阻塞等待(P操作)

P ===》申请资源===》申请一个二值信号量 

int sem_wait(sem_t *sem);
  • 若信号量值为0,则阻塞直到值变为正。
发布(V操作)

 V ===》释放资源===》释放一个二值信号量

int sem_post(sem_t *sem);
  • 增加信号量值,唤醒等待线程。
获取当前值
int sem_getvalue(sem_t *sem, int *sval);
  • 将当前值存入sval(可能因并发不准确)。

注意事项

  1. 进程间共享:需将信号量放在共享内存中,或使用有名信号量(如sem_open)。
  2. 错误处理:所有函数返回-1时表示错误,需检查errno
  3. 资源释放:确保销毁信号量以避免内存泄漏。

计数信号量:计数信号量是一种同步机制,用于控制多个线程或进程对共享资源的访问。与二进制信号量(仅0或1)不同,计数信号量允许一个整数值,表示可用资源的数量。

相关文章:

  • mysql 索引失效有哪些
  • Server 9 ,在 VMware 虚拟机上安装 Windows 系统完整指南
  • LLM中的Loss与Logits详解
  • Femap许可转移操作指南
  • 前后端传输 Long 类型数据时(时间戳,雪花算法ID),精度丢失的根本原因
  • 幸运之轮系统测试报告
  • C++基础:模拟实现vector(有存在深层次的浅拷贝问题)
  • 2G Nand Jlink烧录报错Failed to allocated 0x1B000000 bytes of memory!
  • DeepSeek R1 与 V3 的全面对比,两个版本有什么差别?
  • YOLOv8性能提升:引入华为GhostNetv1特征提取网络
  • 491. Non-decreasing Subsequences
  • C++ 模板元编程语法大全
  • 主题阅读输出-关于成年/成熟的认识-01-学习
  • 6.2 Q1|哈尔滨医科大学GBD发文 | 1990 年至 2019 年颗粒物污染导致的中风全球趋势和负担
  • 数据标注对于模型训练的重要性
  • 自动点焊机如何适应不同厚度的材料焊接?
  • Java、Python、PHP 三种语言实现 二进制与十六进制的相互转换
  • keepalived两台设备同时出现VIP问题
  • MS3494模拟矩阵开关
  • 硬盘驱动器习题解析
  • 冬青街 做网站/沧州网站运营公司
  • 昆山建设网站/百度收录权重
  • 彩票投资理财平台网站建设/河南seo快速排名
  • 网站建设的公司选哪家/东莞免费网站建设网络营销
  • 北京建站模板系统/微信推广多少钱一次
  • 网站建设的报告分析/百度搜索引擎首页