RT-Thread多線程導致的臨界區問題


臨界資源是指一次僅允許一個線程使用的共享資源。不論是硬件臨界資源,還是軟件臨界資源,多個線程必須互斥地對它們進行訪問。每個線程中訪問臨界資源的那段代碼稱為臨
界區( Critical Section),每次只准許一個線程進入臨界區,進入后不允許其他線程進入。多線程程序的開發方式不同於裸機程序,多個線程在宏觀上是並發運行的,因此使用一個共享資源是需要注意,否則就可能出現錯誤的運行結果。

#include <rtthread.h>
#include <stm32f10x.h>
#include "test.h"

rt_uint32_t  g_tmp;/* 定義一個全局變量*/

/*  變量分配4字節對齊 */
ALIGN(RT_ALIGN_SIZE)

/*  靜態線程的 線程堆棧*/
static rt_uint8_t thread1_stack[512];
static rt_uint8_t thread2_stack[512];

/* 靜態線程的 線程控制塊 */
static struct rt_thread thread_test1;
static struct rt_thread thread_test2;


static void test1_thread_entry(void* parameter);
static void test2_thread_entry(void* parameter);

void demo_thread_creat(void)
{
    rt_err_t result;

    /* 創建靜態線程 : 優先級 15 ,時間片 2個系統滴答 */
    result = rt_thread_init(&thread_test1,
                            "test1",
                            test1_thread_entry, RT_NULL,
                            (rt_uint8_t*)&thread1_stack[0], sizeof(thread1_stack), 16, 2);

    if (result == RT_EOK)
    {
        rt_thread_startup(&thread_test1);
    }

    /* 創建靜態線程 : 優先級 16 ,時間片 1個系統滴答 */
    result = rt_thread_init(&thread_test2,
                            "test2",
                            test2_thread_entry, RT_NULL,
                            (rt_uint8_t*)&thread2_stack[0], sizeof(thread2_stack), 15, 1);

    if (result == RT_EOK)
    {
        rt_thread_startup(&thread_test2);
    }

}

void test1_thread_entry(void* parameter)
{
    rt_uint32_t i;

    g_tmp = 0;
    rt_kprintf("g_tmp=:%d \r\n", g_tmp);
    for(i=0; i<10000; i++)
    {
        g_tmp++;
    }
    rt_kprintf("g_tmp=:%d \r\n", g_tmp);
}

void test2_thread_entry(void* parameter)
{
    rt_thread_delay(100);// 1 rt_thread_delay(100);兩種情況下得到兩張圖片

g_tmp++;
}

結果分析:
在 test1 線程的 for 循環中我們對 i 做了 10000 次累加,如果沒有其他線程的“干預”,那么全局變量 g_tmp 的值應該是 10000,現在的輸出結果是 10001,這意味全局變量 g_tmp 的值被線程 2 修改過。整個程序運行過程中各個線程的狀態變化是這樣的: rt_application_init 中創建兩個線程之后,由於 test2 線程的優先級比 test1 線程的優先級高,因此 test2 線程先運行,其線程處理函數第一句為 rt_thread_delay(1), 這會使得 test2 線程被掛起,掛起時間為 1 個時間片,在 test2 線程掛起的這段時間中, test1 線程是所有就緒態線程中優先級最高的線程,因此被內核調度運行。 在 test1 線程執行了一部分代碼后, 1 個 tick 時間到, test2 線程被喚醒,從而成為所有就緒線程中優先級最高的線程,因此會被立刻調度運行, test1 線程被 test2 線程搶占, test2 線程中對全局變量 g_tmp 做累加操作,接下來 test2 線程執行完畢, test1 線程再次被調度運行,根據程序的運行結果可以看出,此時 test1 線程繼續執行,但是我們並不知道此時 test1 線程大致是從什么地方在開始執行的,從最后的輸出結果來看,只能得知此時test1 線程還沒有執行到第二條 rt_kprintf 輸出語句。最后 test1 線程再次打印全局變量 g_tmp的值,其值就應該是 10001。當 test2線程中的第一句為 rt_thread_delay(100)的時候,在 test2線程休眠的整個時間里,test1 線程都已經執行完畢,因此最后的輸出結果為 10000。
從以上可以看到: 當公共資源在多個線程中公用時,如果缺乏必要的保護錯誤,最后的輸出結果可能與預期的結果完全不同。為了解決這種問題,需要引入線程間通信機制,這就
是所謂的 IPC 機制( Inter-Process Communication)。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM