• 临界资源

    • 临界资源 是指 一次 仅允许 一个线程 访问的 共享资源
    • 它可以 是 一个 具体的 硬件设备,也可以 是 一个变量、一个缓冲区
    • 不论是 硬件 临界资源,还是 软件 临界资源,多个线程 必须 互斥地 对它们 进行访问
  • 临界区

    • 每个线程 中 访问(操作)临界资源 的 那段代码 称为临界区(Critical Section),我们 每次 只准许 一个线程 进入 临界区

      uint32_t  value=0;   **// 临界资源**
      
      **/******** 这两个线程都是在系统中调度运行的 ********/
      /**
       * 假设thread1中value的值自加到10000之后,系统开始运行thread2,那么这就和我们本身的设计意图有了偏差
       * 
       * 所以对于对于thread1 和 thread2中访问value的值的** **那段代码 我们需要 分别保护起来
       */**
      void thread1_entry(void * para)
      {                              
          uint32_t i=0;              
          for(i=0;i<10000;i++)       
          {                          
              rt_kprintf(“%d \\r\\n”,value);
              value++;     **// 设计意图:先把临界资源的值从0打印到10000**
          }
      }
      
      void thread2_entry(void * para)   
      {
          rt_thread_delay(50);
          value=500;       **// 设计意图:然后再把临界资源的值赋值成500**
      }
      
  • 临界区保护

    • RT-Thread提供了多种途径来进行临界区保护
      • 方法一:互斥特性保护临界区**(后面讲)**
        • 信号量
        • 互斥量
      • 方法二:关闭系统调度保护临界区
        • 第一种:禁止调度

          • 禁止调度,即是把调度器锁住,不让其进行线程切换。这样就能保证当前运行的任务不被换出,直到调度器解锁,所以禁止调度是常用的临界区保护方法。

            void thread_entry(void* parameter)
            {
                while(1)
                {
                    **/* 调度器上锁 */**      // 上锁后将不再切换到其他线程,仅响应中断
                    rt_enter_critical();
                    /* 以下进入临界区,进行临界资源的访问 */
                    . . . .
                    **/* 调度器解锁 */**
                    rt_exit_critical();
                }
            }
            
        • 第二种:关闭中断

          • 因为所有线程的调度都是建立在中断的基础上的,所以,当我们关闭中断后,系统将不能再进行调度,线程自身也自然不会被其他线程抢占了。

            void thread_entry(void* parameter)
            {         
                rt_base_t level;
                while(1)
                {
                    **/* 关闭中断*/**
                    level = rt_hw_interrupt_disable();
                    /* 以下进入临界区,进行临界资源的访问 */
                    . . . .
                    **/* 关闭中断*/**
                    rt_hw_interrupt_enable(level);
                }
            }