GCD信号量的使用

24 阅读1分钟

信号量

dispatch_semaphore_create:创建一个Semaphore并设置信号的总量;

dispatch_semaphore_signal:发送信号,让信号+1;

dispatch_semaphore_wait:可以使总信号量-1,信号总量小于0时就会等待,阻塞所在线程;

dispatch_semaphore作用:

1)保持线程同步,将异步执行任务转换为同步执行任务

2)保证线程安全,为线程加锁


- (void)gcdSemaphoreSync {
    NSInteger ret = [self gcdRet];
    NSLog(@"异步获取函数返回值 - %ld", ret);
}

- (NSInteger)gcdRet {
    __block NSInteger count = 0;
    dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
    dispatch_queue_t queue = dispatch_queue_create("com.glt.test", DISPATCH_QUEUE_CONCURRENT);
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), queue, ^{//模拟异步网络请求
        count = 999;
        dispatch_semaphore_signal(semaphore);//+1后为0则继续向下执行
    });
    dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);//-1后小于0开始阻塞等待
    return count;
}

//保证线程安全,为线程加锁
- (void)gcdSemaphoreLock {
    if (!_semaphore) {
        _semaphore = dispatch_semaphore_create(1);
    }
    dispatch_queue_t queue = dispatch_queue_create("com.glt.test", DISPATCH_QUEUE_CONCURRENT);
    dispatch_async(queue, ^{
        dispatch_semaphore_wait(self->_semaphore, DISPATCH_TIME_FOREVER);//-1后等于0开始向下进行,之后再执行到这里此处会小于0,产生阻塞,会等待解锁后继续向下执行
        NSLog(@"线程锁-begain");
        sleep(3);
        NSLog(@"线程锁-end");
        dispatch_semaphore_signal(self->_semaphore);//+1后为0,解锁,则继续执行
    });
}

方法调用:

    [self gcdSemaphoreSync];
    [self gcdSemaphoreLock];
    [self gcdSemaphoreLock];
    [self gcdSemaphoreLock];  
    [self gcdSemaphoreSync];
    [self gcdSemaphoreLock];
    [self gcdSemaphoreLock];
    [self gcdSemaphoreLock];

运行结果:


异步获取函数返回值 - 999
线程锁-begain
线程锁-end
线程锁-begain
线程锁-end
线程锁-begain
线程锁-end
异步获取函数返回值 - 999
线程锁-begain
线程锁-end
线程锁-begain
线程锁-end
线程锁-begain
线程锁-end