RT_Thread应用7—信号量1

血红的双手。 提交于 2019-12-22 03:42:33

第十九章 信号量(第一部分)

一、线程同步

  • 同步的介绍:

同步是指按预定的先后次序进行运行,线程同步是指多个线程通过特定的机制来控制线程之间的执行顺序,也可以说是在线程之间通过同步建立起执行顺序的关系,如果没有同步,那线程之间将是无序的。

  • 线程同步的原因

在多任务实时系统中,一项工作的完成往往可以通过多个任务协调的方式共同来完成,
如一个任务从传感器中接收数据并且将数据写到共享内存中,同时另一个任务周期性的从共享内存中读取数据并发送去显示
在这里插入图片描述
如果对共享内存的访问不是排他性的,那么各个线程间可能同时访问它。这将引起数据一致性的问题,
例如:在显示线程Thread#2试图显示数据之前,传感器线程Thread#1还未完成数据的写入,那么显示将包含不同时间采样的数据,易造成显示数据的迷惑。
所以,需要先将传感器数据写入到共享内存完成后,才允许执行传感器数据从共享内存中读出的操作。
**对于操作/访问同一块区域,称之为临界区**。
任务的同步方式的核心思想都是:在访问临界区的时候只允许一个(或一类)任务运行。

二、信号量基本概念

在这里插入图片描述
**概念:**信号量(Semaphore)是一种实现线程间通信的机制,实现线程之间同步或临界资源的互斥访问,常用于协助一组相互竞争的线程来访问临界资源。
信号量就像一把钥匙,把一段临界区给锁住,只允许有钥匙的线程进行访问:线程拿到了钥匙,才允许它进入临界区;而离开后把钥匙传递给排队在后面的等待线程,让后续线程依次进入临界区。
在这里插入图片描述

1、信号量的计数值;
  • 0:表示已经没有积累下来 release 释放信号量操作,且有可能有在此信号量上阻塞的线程。
  • 正值,表示有一个或多个 release 释放信号量操作。
2、信号量使用
  • 互斥——使用信号量

  • 用作互斥时:信号量创建后可用信号量个数应该是满的,线程在需要使用临界资源时,先获取信号量,使其变空防止其他线程需要使用临界资源时就会因为无法获取信号量而进入阻塞,从而保证了临界资源的安全。
    缺点:有可能产生优先级翻转。

  • 同步:一项工作的完成需要通过多个任务协调的方式共同来完成,

  • 用作同步时:假设线程1和线程2需要合作才能完成项目,需要先线程2,后线程1才能完成
    -信号量在创建后被置为空,线程 1 取信号量而阻塞,线程 2 在某种条件发生后,释放信号量,于是线程 1 得以进入就绪态,如果线程 1 的优先级是最高的,那么就会立即切换线程,从而达到了两个线程间的同步。同样的,在中断服务函数中释放信号量,也能达到线程与中断间的同步。

3、信号量目的

为了给临界资源建立一个标志,信号量表示了该临界资源被占用情况。
当一个线程在访问临界资源的时候,就会先对资源信息进行查询,在了解资源被占用的情况后,再做处理,使得临界资源得到有效的保护。

4、计数型信号量

计数型信号量允许多个线程对其进行操作,但限制了线程
的数量。
假设有一个餐厅,只允许50人吃饭,相当于有50个信号量,刚刚开始餐厅位置有50个,那每进去1个人座位就少一个,对应信息量在使用之后也需减一,当座位满了为0,客人就需要排队等待,否则餐厅人会太多,相当于信号量为0,后面的线程对这个停车场资源的访问也无法进行。只有当人离开了,后面的人才可以再进去,因此,当我们释放信号量释放了这个资源,后面的线程才能对这个资源进行访问。

三、二值信号量

-有点类似二进制

  • 信号量资源被获取了,信号量值就是 0,
  • 信号量资源被释放,信号量值就是 1
1、应用场景

在这里插入图片描述

2、运作机制
  • 创建二值信号量,为创建的信号量对象分配内存,并把可用信号量初始化为用户自定义的个数, 二值信号量的最大可用信号量个数为 1。

  • 信号量获取,从创建的信号量资源中获取一个信号量,获取成功返回正确否则线程会等待其它线程释放该信号量超时时间由用户设定。当线程获取信号量失败时,线程将进入阻塞态,系统将线程挂到该信号量的阻塞列表中。

  • L二值信号量无效时,有线程要来获取信号量,则会进入阻塞态

在这里插入图片描述

  • 某个时间中断/线程释放了信号量,则由于获取无效信号量而进入阻塞态的线程将获得信号量由阻塞态变成就绪态

在这里插入图片描述
在这里插入图片描述

四、计数信号量运作机制

  • 概念:计数信号量则允许多个线程获取信号量访问共享资源,不可超过线程的最大数目。
  • 运作机制:访问的线程数达到信号量可支持的最大数目时,会阻塞其他试图获取该信号量的线程,直到有线程释放了信号量。
  • 假设某个资源允许3个线程访问,线程1、2、3已经占用资源,当线程4想要进入资源时会因为获取不到信息量而会变成阻塞态,等到有线程(比如线程 1)释放掉该资源的时候,线程4才能获取到信号量从而进行资源的访问在这里插入图片描述

参考资料:野火 RT-Thread 内核实现与应用开发实战指南
RT-Thread编程手册

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!