「SDL第六篇」孫悟空與多執行緒

lanyu發表於2021-09-09
前言

今天將向大家介紹一下SDL中的多執行緒的使用。透過下面對SDL 執行緒與鎖相關的API,你會發現,它與 Linux, Windows相關的API幾乎是一模一樣的。從這裡可以推斷出,其實SDL對於多執行緒的處理只是為大家提供了一套統一介面,並沒有做其它太多的工作。

這是我們介紹 SDL 的第六篇文章。有興趣的同學可以透過下面的連結檢視其它幾篇文章。

另外,我在慕課網分享了,有興趣的同學可以去觀看。

為啥要用多執行緒?

我覺得這個小節的標題就是一個廢話。不過為了文章的完整性,還是簡單的說一說吧。多執行緒(多程式)是啥意思呢?做個不恰當的比喻,可以把CPU看成一個孫悟空,它有一個能耐,從後腦揪幾個猴毛就可以變出許多的小猴子。

多執行緒(多程式)就是這些小猴子。當幹一件比較複雜的事兒時,可以孫悟空一個人幹,也可以揪幾個猴毛,讓一群小猴子一起幫著幹。這樣一件複雜的事件,分給許多猴子幹,每隻猴只幹一部分,事情很快就被做完了。這樣豈不是比一個人幹要強的多?

當然,有好處也有壞外。猴子多了就需要管理,如果管理不好,就會鬧翻天。比如,只有一塊肉,該給哪個猴子吃呢?這真是一個另人頭痛的問題。

實際上整個作業系統的演進,就是一部管理學的演進。如何才能讓CPU,記憶體,磁碟I/O,各種裝置之間高效的工作,一直是作業系統追求的目標。這話有點扯遠了。

今天我們要講的就是多執行緒(多程式)之間該如何高效的工作。要想讓多執行緒之間高效工作,就要給它們之間立點規矩,大家都要遵守的規矩。這就引入了我們下面的話題。

執行緒互斥與同步

當僧多粥少時,就引入了互斥的概念。再舉個我們生活中的例子吧,比如有一大家族住在同一個大屋子裡,卻只有一個廁所。早上起來大家都想去廁所,這時有誰先搶到了廁所,其它人就只能等他出來後再進入了,這就是互斥

當僅有一份資源,大家都需要時,這就產生了管理問題。解決的辦法就是透過互斥方法來解決。這種情況是在做多執行緒處理時要儘量避免的;如果資源足夠呢?那當然是平均分配,從從有份了。這我們情況是多線路程最希望的。

除了互斥之外,有些情況還需要更精細化的管理,比如說同步。例如車間裡的流水線,每個人負責一塊,每一塊都是半成品,第一個人完成之後交給第二個人做下一步,而後面的人又必須依賴於前而人的結果,依次類推,最後一個人才能完成最終的產品。這就是執行緒間的精細化管理同步

要想實現互斥和同步,就需要一種機制。在作業系統上提供了鎖的概念來達到互斥與同步。

鎖的種類

在作業系統上有很種鎖,有讀寫鎖、自旋鎖、可重入鎖等。下面我簡單的介紹一下它們之間的不同。

讀寫鎖: 分為讀鎖與寫鎖。所謂讀鎖就是被訪問的資源只要你不改變它的值,你就可以訪問,但如果你想改變它,那麼就需要等所有讀它的執行緒都釋放了它們的鎖後,才可以進行修改;寫鎖是同一時刻只能有一個人訪問,當資源被加鎖後,其它人只能等待。

自旋鎖: 償試著給訪問資源加鎖,如果此時被訪問資源已經上鎖了,那就一直不停的償試,直到加鎖成功為止。由於它會非常消耗CPU資源,所以一般只鎖今資源非常短的情況下才能使用它。

可重入鎖: 同一個執行緒對被訪問資源可以一直加鎖。但如果被訪問資源已經上鎖了,那麼其它執行緒則無法對其加鎖。

鎖是解決互斥的一種好辦法,但同樣有利必有弊。如果使用不善就會出現死鎖。

死鎖問題

死鎖顧名思意,就是打不開的鎖。它是怎麼產生的呢?舉個例子,兩個人需要一起完成一件事兒,A說他要等B做完了,他才能開始;而B說它要等A做完了,它才能開使。於時他們在相互等待中老去。

看類很簡單的問題,但這類事情經常在我們的工作中出現。而在我們開發的多執行緒程式中更是頻繁出現。別說人沒遇到過喲!

如何解決?那就是考驗你的管理能力了。共實很多情況是出現了死鎖我們自己卻不知道,否則的話,憑我們的聰名才智怎麼能讓他們一直鎖在那兒呢。

SDL多執行緒

上面介紹了一大堆的理論,現在來看看 SDL 為我們都提供了那些API吧。

  • 建立執行緒

    SDL_Thread* SDL_CreateThread(SDL_ThreadFunction fn,
                             const char*        name,
                             void*              data)
    • fn: 執行緒要執行的函式。
    • name: 執行緒名。
    • data: 函式引數。
  • 等待執行緒

    void SDL_WaitThread(SDL_Thread* thread,
                    int*        status)

    等待執行緒結束。

  • 建立互斥量

    SDL_mutex* SDL_CreateMutex(void)

    也就是建立一個稀有資源,這樣大家就去搶這個資源。從而達到為真正資源加鎖的目的。

  • 銷燬互斥量

    void SDL_DestroyMutex(SDL_mutex* mutex)
  • 加鎖

    int SDL_LockMutex(SDL_mutex* mutex)
  • 解鎖

    int SDL_UnlockMutex(SDL_mutex* mutex)

常用的與執行緒和鎖相關的 API 就以上幾個,是不是非常簡單?下面我們來看一個簡單的例子吧。

例子

下面這個例子是在主執行緒中建立了一個子執行緒。然後主執行緒就一直等待子執行緒結束。等子執行緒結束後,主執行緒也隨之結束。

#include 
#include "SDL.h"

/* Very simple thread - counts 0 to 9 delaying 50ms between increments */
static int TestThread(void *ptr)
{
    int cnt;

    for (cnt = 0; cnt 
小結

本文主要介紹了兩方面的內容。一是對多執行緒理論做了一下簡單的介紹;二是介紹了SDL中與執行緒和鎖相關的API。

最後透過一個例子顯示瞭如何使用 SDL 中的多執行緒。

希望本文能對你有所幫助,謝謝!

隆重推薦

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/2035/viewspace-2808414/,如需轉載,請註明出處,否則將追究法律責任。

相關文章