20 看RTT文档,不太懂有关信号量的死锁问题

发布于 2020-11-14 22:10:52

在《RT-Thread 编程指南》中,有一句关于信号量的描述,
在信号量中,以为已经不存在实例,线程递归持有会发生主动挂起(最终形成死锁)

不太懂什么是实例,什么是线程递归,怎样形成的死锁。

查看更多

关注者
0
被浏览
209
2 个回答
还没想好
还没想好 2020-11-17

线程递归就是线程环境下递归调用某一个函数。信号量递归死锁指是递归获取信号量。信号量的值减到 0,线程挂起,无法执行后续的释放信号量过程,形成死锁。

Glen_Young
Glen_Young 2020-12-16

我的理解是这样的:

这句话的意思是如果一个线程不断获取信号量(没有释放的过程),当信号量的值为0后,线程就会停下,之后就无法运行了,相当于被锁住了。当然这里有个前提,别的线程无法释放这个信号量。

还是举个例子:假设信号量初始值为1,也就是二值信号量
先说正常的使用,我们可以用来保护临界区数据

void thread1_entry(void *parameter)
{
    while (1)
    {
        /* 临 界 区, 上 锁 进 行 操 作 */
        rt_sem_take(&sem_lock, RT_WAITING_FOREVER); /*获取信号量,获取成功后就可以对临界区数据写入*/
        i += 1; /*这里进行数据处理,i为临界区数据*/
        rt_sem_release(&sem_lock); /*释放信号量,让其他线程可以处理临界区数据*/
    }
}

但是如果线程递归调用了信号量,如下面所示(例子可能举的不是很恰当,但是有些时候可能会这样使用)

    void thread1_entry(void *parameter)
    {
        while (1)
        {
            /* 临 界 区, 上 锁 进 行 操 作 */
            rt_sem_take(&sem_lock, RT_WAITING_FOREVER); /*获取信号量,此时信号量为被获取,变成了0*/
            /*
            操作临界区1
            */
                rt_sem_take(&sem_lock, RT_WAITING_FOREVER); /*想再次获取,但是此时由于信号量为0,获取不到就一直等待*/
    /*但是释放信号量的操作在下面,所以信号量根本释放不了,这个线程就锁死在上面那句语句,成了解不开的死锁。
    所以下面的部分永远不会执行到*/
                /*
                操作临界区2
                */
                rt_sem_release(&sem_lock); /*释放信号量,让其他线程可以处理临界区数据*/
            rt_sem_release(&sem_lock); /*释放信号量,让其他线程可以处理临界区数据*/
        }
    }

正因为这样,所以互斥量解决了这个问题,在保护临界区数据时,最好使用互斥量,尤其其解决优先级翻转的问题

撰写答案

请登录后再发布答案,点击登录

发布
问题

分享
好友

手机
浏览

扫码手机浏览