GCD信号量与线程锁

三个函数

1.dispatch_semaphore_t
dispatch_semaphore_create(long value); 创建信号量

参数value须大于或等于0

2.long dispatch_semaphore_wait(dispatch_semaphore_t dsema, dispatch_time_t timeout); // 等位函数

信号量-1,之后

若信号量<0,当前线程被阻塞

若信号量>=0,当前线程继续执行

如果超时返回非0值,否则返回0

3.long dispatch_semaphore_signal(dispatch_semaphore_t dsema);

信号量+1,之后
若信号量>=0, 会唤醒一个正在等待的线程,然后返回

如果有线程被唤醒,返回非0值,否则返回0

类比理解

我喜欢用排队上厕所进行类比,帮助自己理解。

想象一个厕所有三个坑,这个坑位总数就是dispatch_semaphore_create(long value) 函数对应的value

此时三个坑都被人占了,门口又来了一个人,发现没有坑了(信号量为0),只能在门口等着。
对应执行了这个函数dispatch_semaphore_wait,信号量-1后小于0,阻塞当前线程(不能拉也不能撒);

过了一会里面有个人完事儿了,空出一个坑位,他会通知下一个正在等待的人进去。
相当于执行dispatch_semaphore_signal函数,使信号量+1,此时信号量等于0了,唤醒等待的线程,门口的人就可以进去了。

应用举例

1.线程锁

以SDWebImage为例

#define LOCK(lock) dispatch_semaphore_wait(lock, DISPATCH_TIME_FOREVER);
#define UNLOCK(lock) dispatch_semaphore_signal(lock);

_operationsLock = dispatch_semaphore_create(1); // 信号量初始化为1

LOCK(sself.operationsLock);
[sself.URLOperations removeObjectForKey:url]; // 锁内执行,保证只有一个线程访问
UNLOCK(sself.operationsLock);

2.线程同步

- (void)threadSync {
    // 主线程
    dispatch_semaphore_t sema = dispatch_semaphore_create(0);
    __block BOOL allDone = NO;
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
    // 子线程
        allDone = YES;
        dispatch_semaphore_signal(sema);
    });
    dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
    NSLog(@"all done : %d", allDone);
}

子线程执行完之后才会走log, allDone为1

若把dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);注释掉,allDone为0

你可能感兴趣的:(GCD信号量与线程锁)