首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

互斥量、临界区、信号量、事件标志组和消息邮箱

互斥量、临界区、信号量、事件标志组和消息邮箱

为了好的理解互斥量、临界区、信号量、事件标志组和消息邮箱,下面一些知识对初学者来说很重要:    为了实现各任务之间的合作和无冲突的运行,在有关联的任务之间必须建立一些制约关系。这些制约关系主要有两种:直接制约关系和间接制约关系。
    直接制约关系源于任务之间的合作。例如,有两个任务:任务1和任务2,它们需要通过访问同一个数据缓冲区合作完成一项工作,任务1负责向缓冲区写入数据,任务2负责从缓冲区读取数据。显然任务1还未向缓冲区写入数据时(缓冲区为空),任务2因不能从缓冲区得到有效数据而应处于等待状态;只有等任务1向缓冲区写入了数据之后,才应该通知任务2去读取数据。相反,当缓冲区的数据还未被任务2读取时(缓冲区为满时),任务1就不能向缓冲区写入新的数据而应处于等待状态;只有等到任务2自缓冲区中读取数据后,才应该通知任务1去写入数据。显然,如果这两个任务不能如此协调工作,将势必造成严重的后果。
    间接制约关系源于对资源的共享。例如,任务1和任务2共享一台打印机,如果系统已经把打印机分配给了任务1,则任务2因不能获得打印机的使用权而应处于等待状态;只有当任务1把打印机释放后,系统才能唤醒任务2使其获得打印机的使用权。如果这两个任务不这样做,也会造成极大的混乱。
    由上可知,在多任务合作工作的过程中,操作系统应解决两个问题:一是各任务间应具有一种互斥关系,即对于某个共享资源,如果一个任务正在使用,则其他任务只能等待,等到该任务释放该资源后,等待的任务之一才能使用它;二是相关的任务在执行上要有先后次序,一个任务要等其伙伴发来通知,或建立了某个条件后才能继续执行,否则只能等到。
    任务之间的这种制约性的合作运行机制叫做任务间的同步(注意阿,是同步,不是同时啊!)

1 互斥量(mutex)
    1.1 互斥量的定义
    互斥量是一种公共资源,在指定时刻,它只能被一个线程占有(也就是所有权特性),而且占有它的线程可以反复申请这个互斥量。

    1.2 使用互斥量的目的:适合用来控制线程对某些特定资源(比如,临界区和共享资源)
    ① 保护临界区(Critical Section):临界区是一段代码,在执行时不能被其他线程打断,如果要保护它,用互斥量可以实现。举例如下:
    status=tx_mutex_get(&my_mutex,TX_WAIT_FOREVER);//申请互斥量
    if(status!=TX_SUCCESS)  break;//判断是否申请成功
tx_thread_slepp(5);//睡眠5个时钟节拍
status=tx_mutex_put(&my_mutex);//释放互斥量
以上代码就是临界区。
② 提供对共享资源的互斥访问:如果线程想对资源进行独占访问,就必须为每个资源提供对应的互斥量。而在访问资源之前必须为之申请到互斥量,用完之后要把互斥量释放掉,以便其他线程可以使用它来访问资源。

1.3 使用互斥量需要注意的问题
使用互斥量可能会带来死锁的问题和优先级倒置(反转)的问题。
⑴死锁的问题,比如:进程A要调用M资源,而M资源此刻却被进程B占用,且进程B要调用N资源而N资源此刻被A占用,两进程均向CPU发出资源申请,而不释放自己占用的资源,所以两进程均处于暂停状态,这时死锁问题。
    如何避免死锁问题呢?有其中一种方法就是:强制每个进程在同一时刻只能占有一个互斥量,如果一定要只有多个互斥量,可以要求线程必须按相同的顺序来申请互斥量,如:如果线程先得到互斥量1,然后才是互斥量2。
    如果线程进入了死锁状态,怎样从中恢复呢?有下面两种方法:
    ① 在调用tx_mutex_get()函数申请互斥量时,使用超时属性。
    ② 使用tx_thread_wait_abort()中止陷入死锁的线程的挂起状态。

    ⑵优先级倒置(反转)的问题,比如:一个低优先级的线程3某一时刻已经占有互斥量,而此时一个高优先级线程1申请此互斥量,此时级线程1就只能等待,这时如果有一个中优先级线程2已经就绪,那线程2就会中断线程3,从而就会出现线程2先于线程1而执行,这种现象就是优先级倒置问题。
    如何避免优先级倒置?可以让线程3申请的互斥量使用优先级继承的选项来解决这个问题。而优先级继承就是:当出现这种情况(一个低优先级的线程3某一时刻已经占有互斥量,而此时一个高优先级线程1申请此互斥量,此时级线程1就只能等待)时,低优先级线程3就继承高优先级线程的优先级,直到线程3释放互斥量后才恢复其优先级,这样就可以避免优先级倒置的问题。
    1.4 互斥量的一大特性:所有权特性。

2 临界区(Critical Section)
1.1临界区的定义
通过对多线程的串行化来访问公共资源或一段代码,速度快,适合控制数据
访问。
1.2 使用临界区的目的
同步同进程中的线程,保证在某一时刻只有一个线程能访问数据的简便方法
,在任意时刻只允许一个线程对共享资源进行访问。如果有多个线程试图同时访问临界区,那么在有一个进程进入后期他所有试图访问此临界区的线程将被挂起,并一直等到已经进入此临界区的线程离开。

    1.3 互斥量和临界区同步线程的区别
    虽然临界区同步速度很快,但却只能用来同步本进程内的线程,而不可用来同步多个进程中的线程。而互斥量比临界区复杂。因为使用互斥不仅仅能够在同一应用程序不同线程中实现资源的安全共享,而且可以在不同应用程序的线程之间实现对资源的安全共享。

3 信号量(semaphore)
    3.1 信号量的定义
    每个信号量都是公共资源,其值是一个32位计数。信号量的数据结构为一个值和一个指针,指针指向等待该信号量的下一个进程。
信号量的值与相应资源的使用情况有关。当它的值大于0时,表示当前可用资源的数量;当它的值小于0时,其绝对值表示等待使用该资源的进程个数。注意,信号量的值仅能由PV操作来改变。
实现的P,V操作算法描述:
P操作:while s>0
        s=s-1
V操作:s=s+1
P表示申请一个资源,如果条件满足(即右可以分配的资源),则把资源分配给提出申请的进程,并且时资源数目s减1。V表示资源使用哪完毕之后,要把占有的资源释放,并且资源数目s加1 。

3.2 使用信号的场合
⑴ 互斥访问,和互斥量类似,两者的区要区别是:信号量不支持所有权,而所有权是互斥量的核心。当信号量提供互斥访问时,信号量的值代表它允许多少个线程同时访问与之相联系的资源。大多数情况下,提供互斥量的信号量的初值为1,这意味着在任何时刻只有一个线程可以访问相关资源,其值只可能为1或0的信号量一般称为二进制信号量。
使用二进制信号量时,使用者必须避免已经控制了信号量的线程再次调用tx_semaphore_get()来向信号量申请一个实例,如果调用了此项服务,这此调用失败,并将永久性挂起该线程,同时令资源永远不可用。
继承事业,薪火相传
返回列表