GCD中, 有一些函数很常用, 比如同步函数, 异步函数, 障碍函数, 一次性函数等; 另外一些不太常用, 如迭代函数(dispatch_apply), 还有就是今天要说的信号量函数.
今天不打算介绍其他函数, 只说信号量函数.
<br />
- 首先, 什么是信号量? 它有什么用?
以一个停车场的运作为例:
简单起见,假设停车场只有三个车位,一开始三个车位都是空的。
这时如果同时来了五辆车,看门人允许其中三辆直接进入,然后放下车拦,剩下的车则必须在入口等待,此后来的车也都不得不在入口处等待。这时,有一辆车离开停车场,看门人得知后,打开车拦,放入外面的一辆进去,如果又离开两辆,则又可以放入两辆,如此往复。
在这个停车场系统中,车位是公共资源,每辆车好比一个线程,看门人起的就是信号量的作用。
从这段描述我们可以看出, 信号量的作用和互斥锁差不多, 都是保证线程安全的手段.
<br />
- 那么, 信号量函数有哪些? 怎么用?
在GCD中, 有三个函数是semaphore的操作,
分别是:
- dispatch_semaphore_create()
作用: 创建一个semaphore函数, 并设置信号量总数.
参数: 需要传入一个long int的参数, 这个参数就是信号量总数.
返回值: 返回一个dispatch_semaphore_t类型的信号量对象.
- dispatch_semaphore_signal()
作用: 发送一个信号. 相当于给信号量+1.
参数: 需要传入一个信号量对象, 来确定操作哪个信号量函数. - dispatch_semaphore_wait()
作用: 等待信号 . 执行到这里的时候, 如果发现信号量>0, 那么它后面的语句就正常执行, 同时它会给信号量-1; 如果发现信号量<=0, 那么就会一直阻塞在这里, 它后面的语句都不能执行, 直到信号量>0, 才能过掉这个函数.
参数: 需要传入一个信号量对象, 来确定操作哪个信号量函数.
从这段描述我们可以看出, 信号量函数有点类似于障碍函数, 两者都是阻塞型函数.
<br />
- 废话不多说, 直接上代码!
示例代码:
//创建一个信号量为0的semaphore函数. 因为要在block里用这个函数, 记得前面要加上__block.
__block dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
//创建一个并发队列
dispatch_queue_t queue = dispatch_queue_create("StudyBlocks", NULL);
//异步执行
dispatch_async(queue, ^(void)
{
for (int i = 0; i < 5; i ++)
{
NSLog(@">> i: %d", i);
}
dispatch_semaphore_signal(semaphore);
});
//虽然是并发队列+异步函数, 但执行到wait的时候, 发现信号量为0, 所以会阻塞在这里. 直到异步函数里的for循环执行完毕, 然后dispatch_semaphore_signal(semaphore)函数将信号量+1, 才会执行wait后面的for循环.
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
for (int j = 0; j < 5; j ++)
{
NSLog(@">> Main Data: %d", j);
}
运行结果:
test[15518:632061] >> i: 0
test[15518:632061] >> i: 1
test[15518:632061] >> i: 2
test[15518:632061] >> i: 3
test[15518:632061] >> i: 4
test[15518:632036] >> Main Data: 0
test[15518:632036] >> Main Data: 1
test[15518:632036] >> Main Data: 2
test[15518:632036] >> Main Data: 3
test[15518:632036] >> Main Data: 4