GCD信号量(dispatch_semaphore)

上一讲我们谈到可以使用GCD调度组来实现异步处理完成后最后回到某个线程后集中处理(多接口异步请求.回到主线程刷新UI).戳:GCD调度组(dispatch_group)

这一讲我们来谈一个也能实现该需求的GCD信号量(Semaphores)

主要就是下面几个东西

//    dispatch_semaphore_t

//    dispatch_semaphore_create(<#long value#>)
//    dispatch_semaphore_wait(<#dispatch_semaphore_t  _Nonnull dsema#>, <#dispatch_time_t timeout#>)
//    dispatch_semaphore_signal(<#dispatch_semaphore_t  _Nonnull dsema#>)

1.dispatch_semaphore_t

dispatch_semaphore_t类似于dispatch_group_t这种东西就行.创建一个信号量就返回这个东西

2.创建函数

dispatch_semaphore_create(<#long value#>)传入一个long类型数据.返回一个dispatch_semaphore_t.但是这个long类型的数据不能小于0,小于0的话会返回NULL.

3.等待降低信号量

//    dispatch_semaphore_wait(<#dispatch_semaphore_t  _Nonnull dsema#>, <#dispatch_time_t timeout#>)

这个先后顺序并不好描述.因为从代码上下结构来看的话.肯定是先写的提高信号量,然而在执行顺序上来说的话那就是降低信号量在前.

4.提高信号量

//    dispatch_semaphore_signal(<#dispatch_semaphore_t  _Nonnull dsema#>)

提高信号量可以让与之成对的wait失效.然后继续往下执行.
他有一个long类型的返回值,当没有wait的时候就会返回0.

注意:信号量和调度组不一样,需要先降低信号量,然后再提高.如果不成对出现可能会出现EXC_BAD_INSTRUCTION错误,如果先降低信号量(wait)那么就可能导致代码卡死

使用用例

/// 测试 GCD Semaphores
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);

dispatch_async(dispatch_get_global_queue(0, 0), ^{
	NSLog(@"1");
	dispatch_semaphore_signal(semaphore);
});
NSLog(@"5");
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
NSLog(@"6");

dispatch_async(dispatch_get_global_queue(0, 0), ^{
	NSLog(@"2");
	dispatch_semaphore_signal(semaphore);
});
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);

dispatch_async(dispatch_get_global_queue(0, 0), ^{
	NSLog(@"3");
	dispatch_semaphore_signal(semaphore);
});
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);

NSLog(@"4");

输出结果的话是516234

对于多线程有关的东西的话,还是得多次测试才能得出正确结论

加个延时测试一下

    /// 测试 GCD Semaphores
    dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);

    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        [NSThread sleepForTimeInterval:2];
        NSLog(@"1");
        dispatch_semaphore_signal(semaphore);
    });
    NSLog(@"5");
    dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
    NSLog(@"6");

    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        [NSThread sleepForTimeInterval:2];
        NSLog(@"2");
        dispatch_semaphore_signal(semaphore);
    });
    dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);

    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        [NSThread sleepForTimeInterval:2];
        NSLog(@"3");
        dispatch_semaphore_signal(semaphore);
    });
    dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);

    NSLog(@"4");

输出结果还是5.1.6.2.3.4

那么就是.一直顺序执行.如果碰到了dispatch_semaphore_wait.他就会等到接收到signal信号量才会往下走.或者是等到wait的第二个参数(最大等待时间)达到(也算是收到了一个信号量吧).所以必须得在wait之前写下异步任务并且一定能发送出singal信号,或者有最大等待时间.不然会卡死.(直接wait的话线程阻塞.下面不会走.异步任务开在下面等于没开),

GCD的semaphore比较适合用于多个任务需要按某种顺序执行

/// 测试 GCD Semaphores
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);

dispatch_async(dispatch_get_global_queue(0, 0), ^{
	[NSThread sleepForTimeInterval:2];
	NSLog(@"1");
	long longValue = dispatch_semaphore_signal(semaphore);
	NSLog(@"1.longValue:%ld" ,longValue);
});

dispatch_async(dispatch_get_global_queue(0, 0), ^{
	[NSThread sleepForTimeInterval:1];
	NSLog(@"2");
	long longValue = dispatch_semaphore_signal(semaphore);
	NSLog(@"2.longValue:%ld" ,longValue);
});
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);

dispatch_async(dispatch_get_global_queue(0, 0), ^{
	[NSThread sleepForTimeInterval:2];
	NSLog(@"3");
	long longValue = dispatch_semaphore_signal(semaphore);
	NSLog(@"3.longValue:%ld" ,longValue);
});
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);

NSLog(@"4");

如果是上面这种的话,1和2的打印顺序就不一定了.所以说GCD Semaphores很适合用于定制任务执行顺序.

你可能感兴趣的:(多线程)