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

day30——零基础学嵌入式之线程2.0

一、进程和线程的对比

线程进程
定义轻量级的进程。是进程中的执行单元,作为CPU调度的基本单位进程时程序的一次执行过程,作为CPU的资源分配的基本单位
优势
  • 创建以及切换速度块-----效率高
  • 线程(线程共享了进程的资源)间共享资源方便
创建多个子进程,进程之间空间相互独立---进程的稳定性、可靠性、安全性高
缺点
  • 线程间容易产生资源竞争------数据操作可能不是预期效果
  • 线程的可靠性、稳定性,不如进程
进程间,共享数据不方便

二、解决线程资源竞争问题 --- 线程互斥

1.名词解释

  • 临界资源----共享资源
  • 临界区----:一段代码区域(访问临界资源的那段代码)
  • 原子操作----要么不操作,如果要操作,一定是一次性完成的操作,不可被打断;
  • 互斥----在多线程中对临界资源的排他性访问
  • 互斥机制===》互斥锁===》保证临界资源团的访问控制;

        为了保证临界资源(共享资源)的完整操作,增加了锁的机制,即同时满足互斥访问(线程1访问,线程2不可被访问),+原子性操作(访问的整个过程必须完整,不可被打断)。

2.框架:

定义互斥锁 ===》 齿梳化锁 ===》 加锁 ===》 解锁 ===》 销毁

⭐⭐⭐⭐                                                         ⭐⭐⭐    ⭐⭐⭐

3.函数

pthread_mutex_t   +锁命名              【在全局变量中定义】

pthread_mutex_t   +锁命名 +PTHREAD_MUTEX_INITIALIZER                【静态初始化】

pthread_mutex_init();                        【在mian函数定义】【动态初始化】

(1)功能:将已经定义好的互斥锁初始化

(2)参数:

        mutex:要初始化的互斥锁

        atrr:初始化的值,一般默认 NULL;

(3)返回值:

                成功返回0;

                失败返回非0;

pthread_mutex_lock();                             【加锁】

(1)用指定的互斥锁开始加锁代码,加锁后的代码到解锁部分代码属于原子操作;在加锁期间其他进程/线程都不可以操作该部分代码;如果函数在执行的时候,metex以及被其他部分,使用则代码阻塞;

(2)参数:mutex 用来给代码枷锁的互斥锁

(3)返回值

                成功返回0;

                失败返回非零;

pthread_mutex_uhlock();                         【解锁】

(1)功能:将指定的互斥锁解锁,解锁之后代码不在排他访问,一般枷锁解锁成对出现。

(2)参数:用来解锁的互斥锁;

(3)返回值:

                成功返回0;

                失败返回非零

pthread_mutex_d();                                【销毁锁】

(1)功能:销毁互斥锁;

(2)参数:用来销毁的互斥锁;

(3)返回值:

                成功返回0;

                失败返回非零;

代码示例

#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
int cnt =0;
pthread_mutex_t mutex;void *cn1(void *arg)
{ for(int i =0;i<500000;++i){pthread_mutex_lock(&mutex);int tmp = cnt;tmp = tmp+1;cnt = tmp;pthread_mutex_unlock(&mutex);printf("%d\n",cnt);}pthread_exit(NULL);return NULL;
}
void *cn2(void *arg)
{for(int i =0;i<500000;++i){pthread_mutex_lock(&mutex);int tmp = cnt;tmp = tmp+1;cnt = tmp;pthread_mutex_unlock(&mutex);printf("%d\n",cnt);} pthread_exit(NULL);return NULL;
}
int	main(int argc, char **argv)
{pthread_t tid1,tid2;pthread_mutex_init(&mutex, NULL);pthread_create(&tid1, NULL, cn1, NULL);pthread_create(&tid2, NULL, cn2,NULL);pthread_join(tid1, NULL);printf("-------------%d\n",cnt);pthread_mutex_destroy(&mutex);pthread_join(tid2, NULL);return 0;
}

总结:

  • 锁的目的,保证临界资源的互斥以及原子性访问

三、线程间协作-----线程同步

  • 互斥 ===》 在多线程中临界资源的排他性访问
  • 同步 ===》 有一定先后顺序的,对资源的排他性访问。-------有顺序的访问

1.信号量背景:交通信号灯

(1)信号量的机制:

  •         站在a的角度考虑:这块资源什么时候能用
  •         站在b的角度考虑:这块资源什么时候能用

2.信号量分类

  • 信号无名量 ===》 线程间通信
  • 有名信号量 ===》 进程间通信

3.框架

信号量的定义   sem_t   sem;
信号量的初始化  sem_init()
信号量的P操作(申请资源)、V操作(释放资源) sem_wait()/sem_podt();
信号量的销毁sem_destroy()

四、线程同步函数

1、semapthore   信号量的定义   

     sem_t               sem

  信号量类型    信号量的变量

2、信号量的初始化

       int sem_init(sem_t *sem, int pshared, unsigned int value);

(1)功能:将已经定义好的信号量赋值。

(2)参数:

  • sem:要初始化的信号量
  • pthread   =0  :表示线程间使用信号量;

                    !=0:表示进程间使用的信号量

  • value:信号量的初始值,一般无名信号量-------代表一类资源的个数;

(3)返回值:

                成功返回0;

                失败返回-1;

3.P操作、V操作 

P操作------申请资源

(if(是否有资源可用)

                   有;则程序往下使用资源

                  无;程序阻塞,等待资源可用

V操作 ------ 释放资源

                if(是否有仍无需要资源)

                  有:释放资源给对应的任务用;

                  无:让资源个数加一,表示可用的资源数量多了一个,即新产生了一个资源;

int sem_wait(sem_t *sem); 【 P操作】

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

注意:sem申请资源后回自动执行,sem = sem -1;

(2)参数:sem要判断信号量的资源

(3)返回值:

                 成功返回0;

                失败返回-1;

int sem_post(sem_t *sem); 【V操作】

(1)功能 : 函数可以将指定的sem信号量资源释放,并默认执行,sem = sem+1; 线程在该函数上不会阻塞。

(2)参数:sem要释放资源的信号量;

(3)返回值

                 成功返回0;

                失败返回-1;

4.信号量的销毁

 int sem_destroy(sem_t *sem);

 (1)功能:使用完毕将指定的信号量销毁
(2)参数:sem要销毁的信号量
(3)返回值:

                 成功返回0;

                 失败返回-1;

信号的操作:-----主要用来实现线程间的顺序       

示例代码

#include <stdio.h>
#include <pthread.h>
#include <errno.h>
#include <fcntl.h>
#include <string.h>
#include <unistd.h>#include <semaphore.h>
sem_t sem_r;
sem_t sem_w;
char buf[1024] = {0};
void *sh1(void *arg)
{while(1){sem_wait(&sem_w);fgets(buf, sizeof(buf),stdin);sem_post(&sem_r);}
}
void *sh2(void *arg)
{while(1){sem_wait(&sem_r);printf("buf = %s",buf);sem_post(&sem_w);}
}
int	main(int argc, char **argv)
{pthread_t tid1,tid2;sem_init(&sem_w, 0, 1);sem_init(&sem_r, 0, 0);pthread_create(&tid1, NULL, sh1, NULL);pthread_create(&tid2, NULL, sh2, NULL);pthread_join(tid1, NULL);pthread_join(tid1, NULL);return 0;
}

五.应用

1.什么时候用

  • 锁 ----有多线程,公共资源,互斥访问
  • 信号量-----多线程,公共资源,顺序访问

http://www.dtcms.com/a/286674.html

相关文章:

  • 多线程-2-线程间通信
  • 推荐算法召回:架构理解
  • 【RK3576】【Android14】开发环境搭建
  • Windows 下 VS2019 编译 libevent-2.1.10 库
  • React 实现人员列表多选、全选与取消全选功能
  • 大疆司空2私有化部署报错解决方案
  • 谷歌浏览器Chrome的多用户配置文件功能
  • Python分组柱形图绘制全攻略
  • 题解:CF1866D Digital Wallet
  • 熔断和降*的区别
  • 使用pt-toolkit工具包进行MySQL性能优化实战指南
  • 算法训练营day24 回溯算法③ 93.复原IP地址 、78.子集、 90.子集II
  • AWS SSL证书无缝迁移完整指南 - 零业务中断方案
  • Python 进程间通信:TCP安全加密数据传输
  • H3CNE小小综合实验
  • 模拟数据生成---使用NGS数据模拟软件VarBen
  • SLM343CK-DG Sillumin数明半导体高性能LED驱动芯片 抗干扰+耐高温 车载照明专用
  • 二叉树(建立 + 遍历 + 拓展)
  • 外部DLL创建及使用
  • 灵巧手(具身智能入门十一)
  • if (a == 1 a == 2 a == 3)返回true的问题思考
  • NVIDIA 驱动安装失败问题排查与解决(含离线 GCC 工具链安装全过程)
  • MySQL组内拼接group_concat函数
  • MyUI会员排名VcMember组件文档
  • Java与Vue技术搭建的SRM招标采购管理系统,提供源码,涵盖招标、投标、评标全流程,助力企业高效规范采购管理
  • spring-cloud微服务部署-feign服务间调用
  • NFS读写性能评估与优化指南(下)
  • 二叉搜索树:高效的查找结构
  • 自学力扣:最长连续序列
  • python-pptx 的layout 布局