在百米比赛起点,运动员正在等待发令枪响。一旦发令枪响,运动员立即起跑,这就是一种同步。当一个人采摘苹果放入篮子中,另外一个人只要见到篮子中有苹果,就取出加工,这也是一种同步。实时操作系统中也有类似的机制应用于线程之间,或者中断服务程序与线程之间。
为了实现各线程之间的合作和无冲突运行,一个线程的运行过程就需要和其他线程进行配合,线程之间的配合过程称为同步。由于线程间的同步过程通常是由某种条件来触发的,又称为条件同步。在每一次同步的过程中,其中一个线程(或中断)为“控制方”,它使用实时操作系统提供的某种通信手段发出控制信息;另一个线程为“被控制方”,通过通信手段得到控制信息后,进入就绪列表,被实时操作系统调度执行。被控制方的状态由控制方发出的信息的控制,即被控制方的状态由控制方发出的信息来同步。
为了实现线程之间的同步,实时操作系统提供了灵活多样的通信手段,如事件、消息队列、信号量、互斥量等,它们适合不同的场合。
(1)只发同步信号,不需要数据。除了使用事件、信号量、互斥量,在Mbed OS中还可以使用线程信号。同步信号为多个信号的逻辑运算结果时,一般使用事件作为同步手段。
(2)既有同步功能,又能传输数据。可使用消息队列。
若产生数据的速度快于处理速度,就会有未处理的数据堆积,这种情况下只能使用有缓冲功能的通信手段,如消息队列。但是,产生数据的平均速度应该慢于处理速度,否则消息队列会溢出。
在实时操作系统中,有中断与线程之间的同步、两个线程之间的同步、两个以上线程同步一个线程、多个线程相互同步等同步类型。
若一个线程与某一中断相关联,则在中断处理程序中产生同步信号,处于阻塞状态的线程等待这个信号。一旦这个信号发出,该线程就会从阻塞态变为就绪态,接受实时操作系统内核的调度。例如,一个小灯线程与一个串口接收中断相关联,小灯的亮暗切换由串口接收的数据控制,这种情况可用事件方式实现中断和线程之间的同步。在串口接收中断中,当中断处理程序收到一个完整的数据帧时,发出一个事件信号,而当处于阻塞态的小灯线程收到这个事件信号时,就可以进行小灯的亮暗切换。
两个线程之间的同步分为单向同步和双向同步。
(1)单向同步。如果单向同步发生在两个线程之间,那么实际同步效果与两个线程的优先级有很大关系。当控制方线程的优先级低于被控制方线程的优先级时,控制方线程发出信息后使被控制方线程进入就绪态,并立即发生线程切换,然后被控制方线程直接进入激活态,瞬时同步效果较好。当控制方线程的优先级高于被控制方线程的优先级时,控制方线程发出信息后会进入就绪态,但并不发生线程切换,只有当控制方再次调用系统服务函数(如延时函数)使自己挂起时,被控制方线程才有机会运行,其瞬时同步效果较差。在单向同步过程中,必须保证消息的平均生产时间比消息的平均消费时间长,否则,再大的消息队列也会溢出。以采摘苹果与清洗苹果为例,有两个人(A、B),A拿着篮子采摘苹果,篮子最多可以放下20个苹果,B的眼睛盯着A手中的篮子,只要篮子中有苹果,他就“立即”取出清洗干净放在别处,如果A采摘苹果的速度快于B的清洗速度,篮子总有放不下的时候。
(2)双向同步。单向同步中,要求消息的平均生产时间比消息的平均消费时间长,那么如何实现产销平衡呢?可以通过协调生产者和消费者的关系来建立一个产销平衡的理想状态。通信的双方相互制约,生产者通过提供消息来同步消费者,消费者通过回复消息来同步生产者,即生产者必须得到消费者的回复后才能进行下一个消息的生产。这种运行方式称为双向同步,它使生产者的生产速度受到消费者的反向控制,达到产销平衡的理想状态。双向同步的主要功能为确认每次通信均成功,没有遗漏。
当需要由两个以上线程来同步一个线程时,简单的通信方式难以实现,可采用事件按逻辑与来实现,此时被同步线程的执行次数不超过各个同步线程中发出信号最少的线程的执行次数。只要被同步线程的执行速度足够快,被同步线程的执行次数就可以等于各个同步线程中发出信号最少的线程的执行次数。逻辑与的控制功能具有安全控制的特点,它可以用来保障一个重要线程必须在万事俱备的前提下执行。
多个线程相互同步可以将若干相关线程的运行频度保持一致,每个相关线程在运行到同步点时都必须等待其他线程,只有全部相关线程都到达同步点,才可以按优先级的高低依次离开同步点,从而达到相关线程的运行频度保持一致的目的。多个线程相互同步保证在任何情况下各个线程的有效执行次数都相同,而且等于运行速度最低的线程的执行次数。这种同步方式具有团队作战的特点,它可用在一个需要多线程配合进行的循环作业中。