1、理解
GCD中的信号量是指 Dispatch Semaphore,是持有计数的信号。
当计数=0时等待,不可通过。
当计数>=1时,计数减1且不等待,可通过。
dispatch_semaphore_create:创建并初始化信号的总量。
dispatch_semaphore_signal:发送一个信号,让信号总量加1。
dispatch_semaphore_wait:使总信号量减1,当信号总量为0时就等待(阻塞所在线程)。
2、信号量用途
1、控制最大并发量。
2、保持线程同步,将异步执行任务转换为同步执行任务。
3、保证线程安全,为线程加锁。
3、控制最大并发量
// 控制并发队列中,任务的最大并发量为5
dispatch_semaphore_t semaphore = dispatch_semaphore_create(5);
dispatch_queue_t queue = dispatch_queue_create("cwwng-queue", DISPATCH_QUEUE_CONCURRENT);
for (int i=0; i<100; i++) {
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
dispatch_async(queue, ^{
NSLog(@"开始 ---- %d %@", i, [NSThread currentThread]);
sleep(4);
NSLog(@"结束 ++++ %d %@", i, [NSThread currentThread]);
dispatch_semaphore_signal(semaphore);
});
}
2020-11-09 17:22:03.510667+0800 Demo[50332:2567090] 开始 ---- 2 <NSThread: 0x600003bad1c0>{number = 5, name = (null)}
2020-11-09 17:22:03.510669+0800 Demo[50332:2567093] 开始 ---- 0 <NSThread: 0x600003be3680>{number = 4, name = (null)}
2020-11-09 17:22:03.510667+0800 Demo[50332:2567091] 开始 ---- 1 <NSThread: 0x600003bdbc40>{number = 3, name = (null)}
2020-11-09 17:22:03.510669+0800 Demo[50332:2567089] 开始 ---- 3 <NSThread: 0x600003ba8dc0>{number = 6, name = (null)}
2020-11-09 17:22:03.510977+0800 Demo[50332:2567092] 开始 ---- 4 <NSThread: 0x600003bad540>{number = 7, name = (null)}
2020-11-09 17:22:07.512876+0800 Demo[50332:2567093] 结束 ++++ 0 <NSThread: 0x600003be3680>{number = 4, name = (null)}
2020-11-09 17:22:07.512876+0800 Demo[50332:2567089] 结束 ++++ 3 <NSThread: 0x600003ba8dc0>{number = 6, name = (null)}
2020-11-09 17:22:07.512876+0800 Demo[50332:2567090] 结束 ++++ 2 <NSThread: 0x600003bad1c0>{number = 5, name = (null)}
2020-11-09 17:22:07.512876+0800 Demo[50332:2567091] 结束 ++++ 1 <NSThread: 0x600003bdbc40>{number = 3, name = (null)}
2020-11-09 17:22:07.512930+0800 Demo[50332:2567092] 结束 ++++ 4 <NSThread: 0x600003bad540>{number = 7, name = (null)}
2020-11-09 17:22:07.513148+0800 Demo[50332:2567089] 开始 ---- 5 <NSThread: 0x600003ba8dc0>{number = 6, name = (null)}
2020-11-09 17:22:07.513153+0800 Demo[50332:2567090] 开始 ---- 6 <NSThread: 0x600003bad1c0>{number = 5, name = (null)}
2020-11-09 17:22:07.513182+0800 Demo[50332:2567091] 开始 ---- 7 <NSThread: 0x600003bdbc40>{number = 3, name = (null)}
2020-11-09 17:22:07.513212+0800 Demo[50332:2567092] 开始 ---- 8 <NSThread: 0x600003bad540>{number = 7, name = (null)}
2020-11-09 17:22:07.513459+0800 Demo[50332:2567088] 开始 ---- 9 <NSThread: 0x600003ba5fc0>{number = 8, name = (null)}
4、保持线程同步
// 将并发队列中,任务的最大并发量为1
dispatch_semaphore_t semaphore = dispatch_semaphore_create(1);
dispatch_queue_t queue = dispatch_queue_create("cwwng-queue", DISPATCH_QUEUE_CONCURRENT);
for (int i=0; i<100; i++) {
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
dispatch_async(queue, ^{
NSLog(@"开始 ---- %d %@", i, [NSThread currentThread]);
sleep(4);
NSLog(@"结束 ++++ %d %@", i, [NSThread currentThread]);
dispatch_semaphore_signal(semaphore);
});
}
2020-11-09 17:24:22.037069+0800 Demo[50433:2569877] 开始 ---- 0 <NSThread: 0x600002ecea80>{number = 3, name = (null)}
2020-11-09 17:24:26.038963+0800 Demo[50433:2569877] 结束 ++++ 0 <NSThread: 0x600002ecea80>{number = 3, name = (null)}
2020-11-09 17:24:26.039298+0800 Demo[50433:2569877] 开始 ---- 1 <NSThread: 0x600002ecea80>{number = 3, name = (null)}
2020-11-09 17:24:30.044625+0800 Demo[50433:2569877] 结束 ++++ 1 <NSThread: 0x600002ecea80>{number = 3, name = (null)}
2020-11-09 17:24:30.045239+0800 Demo[50433:2569877] 开始 ---- 2 <NSThread: 0x600002ecea80>{number = 3, name = (null)}
2020-11-09 17:24:34.050135+0800 Demo[50433:2569877] 结束 ++++ 2 <NSThread: 0x600002ecea80>{number = 3, name = (null)}
2020-11-09 17:24:34.050509+0800 Demo[50433:2569877] 开始 ---- 3 <NSThread: 0x600002ecea80>{number = 3, name = (null)}
5、保证线程安全
信号量的值设置为1,保证多线程访问安全。
- (void)viewDidLoad {
[super viewDidLoad];
semaphore = dispatch_semaphore_create(1);
dispatch_queue_t queue1 = dispatch_queue_create("cwwng-queue1", DISPATCH_QUEUE_CONCURRENT);
dispatch_queue_t queue2 = dispatch_queue_create("cwwng-queue2", DISPATCH_QUEUE_CONCURRENT);
self.nums = 50;
__weak typeof(self) weakSelf = self;
dispatch_async(queue1, ^{
[weakSelf testAction];
});
dispatch_async(queue2, ^{
[weakSelf testAction];
});
}
- (void)testAction {
while (1) {
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
if (self.nums > 0) {
self.nums--;
NSLog(@"%@", [NSString stringWithFormat:@"倒计时:%d 线程:%@", self.nums, [NSThread currentThread]]);
sleep(2);
dispatch_semaphore_signal(semaphore);
} else {
NSLog(@"倒计时结束");
break;
}
}
}
网友评论