zoukankan      html  css  js  c++  java
  • [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 之后。

  • 相关阅读:
    主流ORM对比分析,莫人云亦云
    避免远程调用中固有的滞后时间问题的最佳方法是进行更少的调用,并让每个调用传递更多的数据。
    挣值管理(PV、EV、AC、SV、CV、SPI、CPI) 记忆
    项目成本管理记忆口诀:
    总是差和自由时差
    成本基线
    php htmlentities函数的问题
    .NET简谈事务、分布式事务处理
    Startup配置类 居然又是约定
    项目管理的九大只是领域输入,工具和输出
  • 原文地址:https://www.cnblogs.com/lyyyuna/p/4123947.html
Copyright © 2011-2022 走看看