YYKit源碼分析---pthread

大家都知道ibireme的YYKit很強大,個人也特別佩服ibireme。大神常常教導(dǎo)我們這樣的小白說:多讀源碼能夠大幅度的提高功力。 <p>YYKit這個框架剛開始看的時候就遇到pthread這個玩意,之前很少接觸。在此,記錄自己的所學(xué)所得,并分享給大家。首推個人blog:iipanda.com,同步更新。

先來看下YY定義的宏

static inline void pthread_mutex_init_recursive(pthread_mutex_t *mutex, bool recursive) {
#define YYMUTEX_ASSERT_ON_ERROR(x_) do { \
__unused volatile int res = (x_); \
assert(res == 0); \
} while (0)
    assert(mutex != NULL);
    if (!recursive) {
        YYMUTEX_ASSERT_ON_ERROR(pthread_mutex_init(mutex, NULL));
    } else {
        pthread_mutexattr_t attr;
        
        YYMUTEX_ASSERT_ON_ERROR(pthread_mutexattr_init (&attr));
        YYMUTEX_ASSERT_ON_ERROR(pthread_mutexattr_settype (&attr, PTHREAD_MUTEX_RECURSIVE));
        YYMUTEX_ASSERT_ON_ERROR(pthread_mutex_init (mutex, &attr));
        YYMUTEX_ASSERT_ON_ERROR(pthread_mutexattr_destroy (&attr));
    }
#undef YYMUTEX_ASSERT_ON_ERROR
}   

大神的代碼都是晦澀難懂的,看到這段代碼后勞資突然產(chǎn)生了好幾個問題:

  • 這個方法是用來干嘛的呢?
  • pthread_mutex_t是什么鬼?
  • pthread_mutexattr_t是用來配置pthread_mutex_t的嗎?

解讀

功能

其實就是創(chuàng)建個互斥線程,并沒有想象中的可怕

pthread_mutex_t

int pthread_mutex_init(pthread_mutex_t * __restrict, const pthread_mutexattr_t * __restrict); 是用這個函數(shù)創(chuàng)建出來的。函數(shù)是以動態(tài)的方式創(chuàng)建互斥鎖的,參數(shù)attr指定了新建互斥鎖的屬性。
recursive這個bool值為false時,attr為空,則使用默認的互斥鎖屬性,默認屬性為快速互斥鎖。
recursive這個bool值為true時,配置互斥鎖屬性創(chuàng)建相應(yīng)的互斥鎖。

YYMUTEX_ASSERT_ON_ERROR

斷言來進行檢查錯誤,所有操作返回非0時,表示有異常錯誤發(fā)生

Mutex type attributes

PTHREAD_MUTEX_NORMAL:不進行deadlock detection(死鎖檢測)。當(dāng)進行relock時,這個mutex就導(dǎo)致deadlock。對一個沒有進行l(wèi)ock或者已經(jīng)unlock的對象進行unlock操作,結(jié)果也是未知的。
PTHREAD_MUTEX_ERRORCHECK:和PTHREAD_MUTEX_NORMAL相比,PTHREAD_MUTEX_ERRORCHECK會進行錯誤檢測,以上錯誤行為都會返回一個錯誤。
PTHREAD_MUTEX_RECURSIVE:和semaphore(信號量)有個類似的東西,mutex會有個鎖住次數(shù)的概念,第一次鎖住mutex的時候,鎖住次數(shù)設(shè)置為1,每一次一個線程unlock這個mutex時,鎖住次數(shù)就會減1。當(dāng)鎖住次數(shù)為0時,其他線程就可以獲得該mutex鎖了。同樣,對一個沒有進行l(wèi)ock或者已經(jīng)unlock的對象進行unlock操作,將返回一個錯誤。
PTHREAD_MUTEX_DEFAULT:默認PTHREAD_MUTEX_NORMAL。

再看看YY如何使用該宏

- (YYImageFrame *)frameAtIndex:(NSUInteger)index decodeForDisplay:(BOOL)decodeForDisplay {
    YYImageFrame *result = nil;
    pthread_mutex_lock(&_lock);
    result = [self _frameAtIndex:index decodeForDisplay:decodeForDisplay];
    pthread_mutex_unlock(&_lock);
    return result;
}

這邊為了防止多線程資源搶奪的問題,先進行l(wèi)ock下,等數(shù)據(jù)操作完畢后釋放unlock,有沒有一種豁然開朗的感覺呢
平時我們在多線程操作的時候也可以使用NSLock、synchronized來進行加鎖,yy使用了更加偏向底層的pthread

pthread_t和NSThread

兩者都是用來操作線程的對象,平時我們使用上層的NSThread比較多,像[NSThread mainThread]獲取主線程,[NSThread currentThread] 獲取當(dāng)前線程。pthread_t和NSThread是一一對應(yīng)的,同樣可以通過pthread_main_thread_np() 、pthread_self()來獲取。NSThread只是對pthread_t的一層封裝而已。

實戰(zhàn)

  • 聲明函數(shù)
void *func(void *argu) {
    char *m = (char *)argu;

    pthread_mutex_lock(&mutex);
    while (*m != '\0') {
        printf("%c", *m);
        fflush(stdout);
        sleep(3);
        m++;
    }
    printf("\n");
    pthread_mutex_unlock(&mutex);
    return 0;
}
  • mutex使用
    int rc1, rc2;
    
    char *str1 = "Hi";
    char *str2 = "Boy!";
    
    pthread_t thread1, thread2;
    pthread_mutex_init(&mutex, NULL);

    if ((rc1 = pthread_create(&thread1, NULL, func, str1))) {
        fprintf(stdout, "thread1 creat fail : %d \n!", rc1);
    }
    if ((rc2 = pthread_create(&thread2, NULL, func, str2))) {
        fprintf(stdout, "thread2 creat fail : %d \n!", rc2);
    }

    // https://developer.apple.com/legacy/library/documentation/Darwin/Reference/ManPages/man3/pthread_join.3.html#//apple_ref/c/func/pthread_join
    // 等待一個線程的結(jié)束,當(dāng)函數(shù)返回時,被等待的線程資源被收回。若線程已經(jīng)被收回,那么該函數(shù)會立即返回
    pthread_join(thread1, NULL);
    pthread_join(thread2, NULL);

    printf("這邊只有線程被回收后才會執(zhí)行!");
  • 可以幫pthread_mutex_lock(&mutex)和pthread_mutex_unlock(&mutex)注釋掉看下打印<p>

感謝大家花費時間來查看這篇blog,需要下載demo的同學(xué)請猛戳Git。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 接著上上節(jié) thread ,本節(jié)主要介紹mutex的內(nèi)容,練習(xí)代碼地址。<mutex>:該頭文件主要聲明了與互斥量...
    jorion閱讀 12,688評論 2 4
  • iOS線程安全的鎖與性能對比 一、鎖的基本使用方法 1.1、@synchronized 這是我們最熟悉的枷鎖方式,...
    Jacky_Yang閱讀 2,371評論 0 17
  • 引用自多線程編程指南應(yīng)用程序里面多個線程的存在引發(fā)了多個執(zhí)行線程安全訪問資源的潛在問題。兩個線程同時修改同一資源有...
    Mitchell閱讀 2,108評論 1 7
  • 朋友圈中有些故事,很多父母發(fā)現(xiàn)自己常常會跟兒子開一些無厘頭的玩笑。有時覺得真的沒什么,但是孩子卻容易當(dāng)真。這也是讓...
    好彩妹閱讀 276評論 0 0

友情鏈接更多精彩內(nèi)容