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

学习嵌入式的第二十九天-数据结构-(2025.7.16)线程控制:互斥与同步

以下是您提供的文本内容的排版整理版本。我已根据内容主题将其分为几个主要部分(互斥锁、信号量、死锁、IPC进程间通信、管道操作),并使用清晰的结构组织信息:

  • 代码片段用代码块格式(指定语言为C)突出显示。
  • 函数定义和步骤使用有序列表整理。
  • 关键概念用加粗或小标题强调。
  • 整体结构基于逻辑顺序优化,确保易读性,但未修改原始内容含义。

互斥锁机制

互斥机制确保多线程中对临界资源的排他性访问(公共资源)。框架包括定义、初始化、加锁、解锁和销毁步骤。

  1. 定义互斥锁

    pthread_mutex_t mutex; // 互斥锁类型变量
    

  2. 初始化锁

    • 函数:int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr);
      • 功能:初始化已定义的互斥锁。
      • 参数:
        • mutex:要初始化的互斥锁指针。
        • attr:初始化属性值,通常为NULL(表示默认锁)。
      • 返回值:成功返回0,失败返回非零值。
  3. 加锁

    • 函数:int pthread_mutex_lock(pthread_mutex_t *mutex);
      • 功能:对指定代码加锁,加锁后代码为原子操作(其他线程无法访问)。
      • 参数:mutex为互斥锁指针。
      • 返回值:成功返回0,失败返回非零值。
      • 注意:如果锁已被占用,则阻塞当前线程。
  4. 解锁

    • 函数:int pthread_mutex_unlock(pthread_mutex_t *mutex);
      • 功能:解锁指定互斥锁。
      • 参数:mutex为互斥锁指针。
      • 返回值:成功返回0,失败返回非零值。
      • 注意:加锁和解锁通常成对出现。
  5. 销毁锁

    • 函数:int pthread_mutex_destroy(pthread_mutex_t *mutex);
      • 功能:销毁互斥锁。
      • 参数:mutex为互斥锁指针。
      • 返回值:成功返回0,失败返回非零值。
  6. 非阻塞锁(trylock)

    • 函数:int pthread_mutex_trylock(pthread_mutex_t *mutex);
      • 功能:类似加锁,但不阻塞。
      • 参数:mutex为互斥锁指针。
      • 返回值:成功返回0,失败返回非零值(如EAGAIN)。
    • 注意:互斥锁控制排他访问,但不保证次序。

信号量机制(Linux线程同步)

信号量用于线程或进程间同步,分类为:

  • 无名信号量:线程间通信。
  • 有名信号量:进程间通信。

框架包括定义、初始化、PV操作和销毁。

  1. 定义信号量

    sem_t sem; // 信号量类型变量
    

  2. 初始化信号量

    • 函数:int sem_init(sem_t *sem, int pshared, unsigned int value);
      • 功能:初始化已定义的信号量。
      • 参数:
        • sem:信号量指针。
        • pshared0表示线程间使用,非0表示进程间使用。
        • value:初始值(例如,二值信号量中,0表示阻塞,1表示通过)。
      • 返回值:成功返回0,失败返回非零值。
  3. PV操作

    • P操作(申请资源):sem_wait(sem_t *sem);(功能:减少信号量值,如果值为0则阻塞)。
    • V操作(释放资源):sem_post(sem_t *sem);(功能:增加信号量值,唤醒等待线程)。
    • 注意:PV操作确保同步。
  4. 销毁信号量

    • 函数:int sem_destroy(sem_t *sem);
      • 功能:销毁信号量。
      • 参数:sem为信号量指针。
      • 返回值:成功返回0,失败返回非零值。

死锁原因与必要条件

死锁产生原因:

  1. 系统资源不足。
  2. 进程运行推进顺序不合适。
  3. 资源分配不当。

死锁必要条件:

  1. 互斥条件:一个资源每次只能被一个进程使用。
  2. 请求与保持条件:进程因请求资源阻塞时,对已获得资源保持不放。
  3. 不剥夺条件:进程已获得资源在未使用完前不能被强行剥夺。
  4. 循环等待条件:若干进程形成头尾相接的循环等待资源关系。

注意:如果资源充足,死锁可能性低;否则易因争夺资源发生。


IPC进程间通信分类

IPC(Inter-Process Communicate)分为三大类:

  1. 古老通信方式

    • 无名管道。
    • 有名管道。
    • 信号(唯一异步通信方式)。
  2. IPC对象通信(System V)

    • 消息队列(较少使用)。
    • 共享内存(最高效方式)。
    • 信号量集。
  3. Socket通信:用于网络通信。

特例:线程信号使用sem_init(POSIX标准)。


管道操作(有名管道)

管道操作框架:打开、读写、关闭、卸载。

  1. 打开有名管道

    • 函数:int open(const char *pathname, int flags);
      • 注意:
        • 管道为半双工模式,打开方式决定读写端。
        • 示例:
          int fd_read = open("./fifo", O_RDONLY); // 固定为读端
          int fd_write = open("./fifo", O_WRONLY); // 固定为写端
          

        • 禁止使用O_RDWR(读写模式)或O_CREAT(创建选项),管道创建需用mkfifo函数。
  2. 管道读写

    • 读操作:read(fd_read, buff, sizeof(buff));
    • 写操作:write(fd_write, buff, sizeof(buff));
  3. 关闭管道

    • 函数:close(fd);
  4. 卸载管道

    • 函数:int unlink(const char *pathname);
      • 功能:移除管道文件。

http://www.lryc.cn/news/600028.html

相关文章:

  • php语法--foreach和in_array的使用
  • 环境变量-进程概念(7)
  • PowerDesigner安装教程(附加安装包)PowerDesigner详细安装教程PowerDesigner 16.6 最新版安装教程
  • 7.文件操作:让程序读写文件 [特殊字符]
  • haproxy七层代理(原理)
  • 【07】C#入门到精通——C# 生成dll库 C#添加现有DLL C#调用自己生成的dll库
  • Typecho多语言解决方案:从插件到主题的完整实现
  • CANoe入门(11)-- 诊断模块
  • SpringBoot学习路径--SpringBoot的简单介绍和项目搭建
  • c++注意点(13)----设计模式(抽象工厂)
  • 医疗器械:DFEMA和PFEMA
  • 从数据脱敏到SHAP解释:用Streamlit+XGBoost构建可复现的川崎病诊断系统
  • [NLP]一个完整的 UPF 文件示例
  • 文心4.5横向对标全球大模型:技术突破与应用前景深度分析
  • OSPF 路由协议多区域
  • 利用Dify实现应用日志关键信息提取之实践
  • 九联UNT413AS_晶晨S905L3S芯片_2+8G_安卓9.0_线刷固件包
  • RK3588 HDMI-RX 驱动、RGA 加速与 OpenCV GStreamer 支持完整指南
  • React性能优化终极指南:memo、useCallback、useMemo全解析
  • 堆(Heap)优先级队列(Priority Queue)
  • python基础:request模块简介与安装、基本使用,如何发送get请求响应数据,response属性与请求头
  • 《计算机组成原理与汇编语言程序设计》实验报告一 基本数字逻辑及汉字显示
  • 机器学习详解(28):LightGBM原理
  • Linux系统编程——进程
  • 腾讯云CodeBuddy+微信小程序:5分钟开发番茄小闹钟
  • IPv6,你开始使用了吗?
  • 学习日志18 python
  • 从入门到进阶:JavaScript 学习之路与实战技巧
  • [科普] 快速傅里叶变换(FFT)和离散傅里叶变换(DFT)的差异
  • JDK8保姆级安装教程