[RTT例程练习] 1.6 线程优先级反转原理

优先级反转是不希望出现的现象。

简单来说,有三个线程A, B, C, 优先级A>B>C,A和C有共享资源S。A.B挂起,C运行且有S,A没有S所以一直挂起,B进入调度,调度完之后C再运行直到释放S之后,A才能运行。

可以看出,A虽然优先级最高,但实际运行却是最后一个运行,其实际的优先级反转了。

下面这段来自官网:

三个线程的优先级顺序是 thread2 > worker > thread1,首先thread2得到执行,它得到信号量,并且释放,然后延时等待,然后worker线程得到处理器控制权开始运行,它也进行了延时操作,然后,thread1拿到了控制权,并且它申请得到了信号量,接着进行了打印操作,在它打印结束进行延时操作时,由于worker的优先级高于thread1,worker重新获得了控制,由于它并不需要信号量来完成下面的操作,于是很顺利的它把自己的一大串打印任务都执行完成了,纵然thread2的优先级要高于它,但是奈何获取不到信号量,什么也干不了,只能被阻塞而干等,于是实验原理中提到的那一幕便发生了。worker执行结束后,执行权回到了握有信号量的thread1手中,当它完成自己的操作,并且释放信号量后,优先级最高的thread2才能继续执行。

对应程序:

#include <rtthread.h>

static rt_sem_t sem;
static rt_uint8_t t1_count, t2_count, worker_count;
static rt_thread_t t1, t2, worker;

static void thread1_entry(void *parameter)
{
    rt_err_t result;
    
    result = rt_sem_take(sem, RT_WAITING_FOREVER);
    
    for (t1_count = 0; t1_count < 10; t1_count++)
    {
        rt_kprintf("thread1: got semaphore, count: %d\n", t1_count);
        rt_thread_delay(RT_TICK_PER_SECOND);
    }
    
    rt_kprintf("thread1: release semaphore\n");
    rt_sem_release(sem);
}

static void thread2_entry(void *parameter)
{
    rt_err_t result;
    
    while (1)
    {
        result = rt_sem_take(sem, RT_WAITING_FOREVER);
        rt_kprintf("thread2: got semaphore\n");
        if (result != RT_EOK)
            return;
        rt_kprintf("thread2: release semaphore\n");
        rt_sem_release(sem);

        rt_thread_delay(90);
        result = rt_sem_take(sem, RT_WAITING_FOREVER);
        t2_count++;
        rt_kprintf("thread2: got semaphore, count: %d\n", t2_count);
    }
}

static void worker_thread_entry(void *parameter)
{
    rt_thread_delay(5);
    for (worker_count = 0; worker_count < 10; worker_count++)
    {
        rt_kprintf("worker: count: %d\n", worker_count);
    }
    rt_thread_delay(RT_TICK_PER_SECOND);
}

int rt_application_init()
{
    sem = rt_sem_create("sem", 1, RT_IPC_FLAG_PRIO);
    if (sem ==RT_NULL)
    {
        return 0;
    }
    
    t1_count = t2_count = 0;
    
    t1 = rt_thread_create("t1",
        thread1_entry, RT_NULL,
        512, 7, 10);
    if (t1 != RT_NULL)            
        rt_thread_startup(t1);
        
    t2 = rt_thread_create("t2",
        thread2_entry, RT_NULL,
        512, 5, 10);
    if (t2 != RT_NULL)
        rt_thread_startup(t2);
    
    worker = rt_thread_create("worker",
        worker_thread_entry, RT_NULL,
        512, 6, 10);
    if (worker != RT_NULL)
        rt_thread_startup(worker);
        
    return 0;
}
/*@}*/  

输出结果为:

thread2: got semaphore
thread2: release semaphore
thread1: got semaphore, count: 0
worker: count: 0
worker: count: 1
worker: count: 2
worker: count: 3
worker: count: 4
worker: count: 5
worker: count: 6
worker: count: 7
worker: count: 8
worker: count: 9
thread1: got semaphore, count: 1
thread1: got semaphore, count: 2
thread1: got semaphore, count: 3
thread1: got semaphore, count: 4
thread1: got semaphore, count: 5
thread1: got semaphore, count: 6
thread1: got semaphore, count: 7
thread1: got semaphore, count: 8
thread1: got semaphore, count: 9
thread1: release semaphore
thread2: got semaphore, count: 1

可以看到thread2 被降到了 thread1 和 worker 之后。

posted @ 2013-02-18 11:37  lyyyuna  阅读(304)  评论(0编辑  收藏  举报