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

学习嵌入式第三十天

文章目录

  • 进程和线程(续)
    • 线程
      • 1.线程传参
      • 2.线程属性
      • 3.线程间通信
        • 1.概念
        • 2.方式
        • 3.互斥锁
        • 4.死锁
        • 5.信号量
  • 习题

进程和线程(续)

线程

1.线程传参

  • 使用第四个参数实现对线程内部的传参

    代码实现:

    #include <stdio.h>
    #include <string.h>
    #include <dirent.h>
    #include <sys/types.h>
    #include <pthread.h>
    #include <unistd.h>typedef struct pthread_arg{pthread_t tid;char threadname[32];int sleeptime;
    }pthread_arg_t;void *thread(void *arg){pthread_arg_t *parg = arg;printf("%s(TID:%#lx)开始执行\n",parg->threadname,parg->tid);while(1){printf("%s正在执行\n",parg->threadname);sleep(parg->sleeptime);}return NULL;
    }int main(void){int i = 0;pthread_arg_t args[4] = {{0,"采集线程", 1},{0, "存储线程", 2},{0, "显示线程", 5},{0, "日志线程", 10}};for(i = 0;i < 4;i++){pthread_create(&args[i].tid,NULL,thread,&args[i]);}for(i = 0;i < 4;i++){pthread_join(args[i].tid,NULL);}return 0;
    }
    

2.线程属性

  • 加入属性:线程结束需要pthread_join手动回收,但是可以完成线程间同步
  • 分离属性:线程结束后系统自动回收线程空间
  1. pthread_attr_init

    原型:int pthread_attr_init(pthread_attr_t *attr);
    功能:线程属性初始化
    参数:attr:线程属性空间的首地址
    
  2. pthread_attr_setdetachstate

    原型:int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate);
    功能:将线程属性设置为分离属性
    参数:attr:线程属性空间的首地址detachstate:属性PTHREAD_CREATE_DETACHED	分离属性PTHREAD_CREATE_JOINABLE	加入属性
    
  3. pthread_attr_destroy

    原型:int pthread_attr_destroy(pthread_attr_t *attr);
    功能:线程属性销毁
    参数:attr:线程属性空间的首地址
    

3.线程间通信

1.概念
  • 多个线程间传递信息
2.方式

采用全局变量

  • 原因:进程是操作系统分配的最小单元;每个进程空间独立,包含文本段,数据段(全局变量),系统数据段;一个进程中的多个线程独享栈空间,而文本段,数据段,堆区进程多线程共享
  • 多线程同时操作共享空间会引发资源竞争,需要加上互斥锁解决资源竞争问题
3.互斥锁
  1. 概念

    • 解决资源竞争的一种方式,可以看成是一种资源

    • 只能加锁一次,加锁期间不能再次加锁,也不能强制占有一个已经加锁的锁资源,必须等待锁资源释放,也就是解锁后才能继续操作该锁

    • 加锁和解锁中间的代码称为临界代码,也称为临界区

    • 只能防止多个线程对资源的竞争,不能决定代码的先后执行顺序

    • 原子操作:CPU执行原子操作时无法切换调度任务

  2. 使用方式

    • 定义互斥锁
    • 对锁初始化
    • 操作全局资源前先加锁
    • 如果加锁成功则完成对全局资源操作
    • 如果加锁失败则表示有人占用资源,必须等待其余人释放锁资源才能加锁成功
    • 直到加锁成功使用该全局资源
  3. 函数接口

    1. pthread_mutex_init

      原型:int pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restrict attr);
      功能:初始化互斥锁
      参数:mutex:互斥锁空间首地址attr:属性,默认为NULL
      返回值:成功返回0失败返回-1
      
    2. pthread_mutex_lock

      原型:int pthread_mutex_lock(pthread_mutex_t *mutex);
      功能:互斥锁加
      
    3. pthread_mutex_unlock

      原型:int pthread_mutex_unlock(pthread_mutex_t *mutex);
      功能:互斥锁解
      
    4. pthread_mutex_destroy

      原型:int pthread_mutex_destroy(pthread_mutex_t *mutex);
      功能:互斥锁销毁
      
4.死锁
  1. 概念
    • 多线程由于加锁解锁不合理导致程序无法继续向下运行的状态
  2. 产生的条件
    • 互斥条件
    • 不可剥夺条件
    • 请求保持条件
    • 循环等待条件
  3. 避免死锁
    • 加锁顺序保持一致
    • 使用pthread_mutex_trylock替换pthread_mutex_lock
5.信号量
  1. 概念

    • 信号量是一种资源
    • 信号量只能完成初始化,销毁,申请,释放四种操作
    • 如果信号量资源数为0,申请资源会阻塞等待,直到占用资源的任务释放资源,资源数不为0时才能申请到资源并继续向下执行
    • 释放资源不会阻塞
  2. 函数接口

    1. sem_init

      原型:int sem_init(sem_t *sem, int pshared, unsigned int value);
      功能:初始化信号量
      参数:sem:信号空间首地址pshared:0:一个进程的多个线程间共享!0:多个进程间共享value:初始化的资源的值	
      返回值:成功返回0失败返回-1
      
    2. sem_destroy

      原型:int sem_destroy(sem_t *sem);
      功能:销毁信号量
      参数:sem:信号量空间的首地址
      返回值:成功返回0失败返回-1
      
    3. sem_wait

      原型:int sem_wait(sem_t *sem);
      功能:申请信号量
      参数:sem:信号量空间的首地址
      返回值:成功返回0失败返回-1
      
      • 申请信号量会使信号量资源数为-1
      • 如果信号量资源数为0,则会阻塞等待,直到有任务释放资源,才能拿到资源并继续向下执行
    4. sem_post

      原型:int sem_post(sem_t *sem);
      功能:
      释放信号量
      参数:
      sem:信号量空间首地址
      返回值:
      成功返回0
      失败返回-1
      

习题

编写三个线程任务,线程一循环打印‘A’,线程一循环打印‘B’,线程一循环打印‘C’,要求打印出的字符顺序总为ABC

代码实现:

#include<stdio.h>
#include<pthread.h>
#include<unistd.h>
#include<stdlib.h>
#include<semaphore.h>sem_t sem_wa;
sem_t sem_wb;
sem_t sem_wc;void *thread1(void *arg){while(1){sem_wait(&sem_wa);printf("A\n");sem_post(&sem_wb);}return NULL;
}
void *thread2(void *arg){while(1){sem_wait(&sem_wb);printf("B\n");sem_post(&sem_wc);}return NULL;
}
void *thread3(void *arg){while(1){sem_wait(&sem_wc);printf("C\n");sem_post(&sem_wa);}return NULL;
}int main(void){pthread_t tid1;pthread_t tid2;pthread_t tid3;sem_init(&sem_wa,0,1);sem_init(&sem_wb,0,0);sem_init(&sem_wc,0,0);pthread_create(&tid1,NULL,thread1,NULL);pthread_create(&tid2,NULL,thread2,NULL);pthread_create(&tid3,NULL,thread3,NULL);pthread_join(tid1,NULL);pthread_join(tid2,NULL);pthread_join(tid3,NULL);sem_destroy(&sem_wa);sem_destroy(&sem_wb);sem_destroy(&sem_wc);return 0;
}
http://www.lryc.cn/news/622624.html

相关文章:

  • WSL中占用磁盘空间大问题解决
  • 通过rss订阅小红书,程序员将小红书同步到自己的github主页
  • 消息中间件Tibco 和 Kafka 及 Pulsar
  • 【LeetCode 热题 100】70. 爬楼梯——(解法二)自底向上
  • 《从入门到精通:Kafka核心原理全解析》
  • 博弈论07——Lemke-Howson 算法
  • EXTI外部中断的执行逻辑|以对射式红外传感器计次为例
  • 九尾狐未来机械锂晶核
  • 【数据结构初阶】--排序(五):计数排序,排序算法复杂度对比和稳定性分析
  • 0815 UDP通信协议TCP并发服务器
  • JavaEE 初阶第十九期:网络编程“通关记”(一)
  • MM-Spatial和Spatial-MLLM论文解读
  • 使用IntersectionObserver实现页面右侧运营位区域固定,和页面列表数据分页加载
  • Java后台生成多个Excel并用Zip打包下载
  • 深入剖析 TOTP 算法:基于时间的一次性密码生成机制
  • Mac (三)如何设置环境变量
  • 常见的地理空间架构及其编码
  • 【科研绘图系列】R语言绘制雷达图
  • 编写和运行 Playbook
  • Hana IDE 安装吧报错
  • Java内功修炼(1)——时光机中的并发革命:从单任务到Java多线程
  • PAT 1067 Sort with Swap(0, i)
  • AI的下一个竞争焦点——世界模型
  • 图像相似度算法汇总及Python实现
  • webrtc弱网-VideoSendStreamImpl类源码分析与算法原理
  • CodeBuddy IDE深度体验:AI驱动的全栈开发新时代
  • 二分查找。。
  • 抽象代数 · 代数结构 | 群、环、域、向量空间
  • Windows MCP.Net:基于.NET的Windows桌面自动化MCP服务器深度解析
  • MixOne:Electron Remote模块的现代化继任者