YYKit源码分析---pthread

大家都知道ibireme的YYKit很强大,个人也特别佩服ibireme。大神常常教导我们这样的小白说:多读源码能够大幅度的提高功力。 <p>YYKit这个框架刚开始看的时候就遇到pthread这个玩意,之前很少接触。在此,记录自己的所学所得,并分享给大家。首推个人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
}   

大神的代码都是晦涩难懂的,看到这段代码后劳资突然产生了好几个问题:

  • 这个方法是用来干嘛的呢?
  • pthread_mutex_t是什么鬼?
  • pthread_mutexattr_t是用来配置pthread_mutex_t的吗?

解读

功能

其实就是创建个互斥线程,并没有想象中的可怕

pthread_mutex_t

int pthread_mutex_init(pthread_mutex_t * __restrict, const pthread_mutexattr_t * __restrict); 是用这个函数创建出来的。函数是以动态的方式创建互斥锁的,参数attr指定了新建互斥锁的属性。
recursive这个bool值为false时,attr为空,则使用默认的互斥锁属性,默认属性为快速互斥锁。
recursive这个bool值为true时,配置互斥锁属性创建相应的互斥锁。

YYMUTEX_ASSERT_ON_ERROR

断言来进行检查错误,所有操作返回非0时,表示有异常错误发生

Mutex type attributes

PTHREAD_MUTEX_NORMAL:不进行deadlock detection(死锁检测)。当进行relock时,这个mutex就导致deadlock。对一个没有进行lock或者已经unlock的对象进行unlock操作,结果也是未知的。
PTHREAD_MUTEX_ERRORCHECK:和PTHREAD_MUTEX_NORMAL相比,PTHREAD_MUTEX_ERRORCHECK会进行错误检测,以上错误行为都会返回一个错误。
PTHREAD_MUTEX_RECURSIVE:和semaphore(信号量)有个类似的东西,mutex会有个锁住次数的概念,第一次锁住mutex的时候,锁住次数设置为1,每一次一个线程unlock这个mutex时,锁住次数就会减1。当锁住次数为0时,其他线程就可以获得该mutex锁了。同样,对一个没有进行lock或者已经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;
}

这边为了防止多线程资源抢夺的问题,先进行lock下,等数据操作完毕后释放unlock,有没有一种豁然开朗的感觉呢
平时我们在多线程操作的时候也可以使用NSLock、synchronized来进行加锁,yy使用了更加偏向底层的pthread

pthread_t和NSThread

两者都是用来操作线程的对象,平时我们使用上层的NSThread比较多,像[NSThread mainThread]获取主线程,[NSThread currentThread] 获取当前线程。pthread_t和NSThread是一一对应的,同样可以通过pthread_main_thread_np() 、pthread_self()来获取。NSThread只是对pthread_t的一层封装而已。

实战

  • 声明函数
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
    // 等待一个线程的结束,当函数返回时,被等待的线程资源被收回。若线程已经被收回,那么该函数会立即返回
    pthread_join(thread1, NULL);
    pthread_join(thread2, NULL);

    printf("这边只有线程被回收后才会执行!");
  • 可以帮pthread_mutex_lock(&mutex)和pthread_mutex_unlock(&mutex)注释掉看下打印<p>

感谢大家花费时间来查看这篇blog,需要下载demo的同学请猛戳Git

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,080评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,422评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,630评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,554评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,662评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,856评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,014评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,752评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,212评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,541评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,687评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,347评论 4 331
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,973评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,777评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,006评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,406评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,576评论 2 349

推荐阅读更多精彩内容