GCD 信号量:dispatch_semaphore
信号量:就是一种可用来控制访问资源的数量的标识,设定了一个信号量,在线程访问之前,加上信号量的处理,则可告知系统按照我们指定的信号量数量来执行多个线程。
Dispatch Semaphore 在实际开发中主要用于:
保持线程同步,将异步执行任务转换为同步执行任务;保证线程安全,为线程加锁。
Dispatch Semaphore提供了三个函数。
dispatch_semaphore_create(long value):这个函数是创建一个dispatch_semaphore_类型的信号量,并且创建的时候需要指定信号量的大小。这里的传入的参数value必须大于或等于0,否则dispatch_semaphore_create会返回NULL。
dispatch_semaphore_wait(dispatch_semaphore_t dsema, dispatch_time_t timeout):等待信号量。如果信号量值为0,那么该函数就会一直等待,也就是不返回(相当于阻塞当前线程),直到该函数等待的信号量的值大于等于1,该函数会对信号量的值进行减1操作,然后返回。
dispatch_semaphore_signal(dispatch_semaphore_t deem):发送信号量。该函数会对信号量的值进行加1操作。
注意:通常等待信号量和发送信号量的函数是成对出现的。
- (void)semaphoreSync {
NSLog(@"%@",[NSThread currentThread]);
NSLog(@"begin");
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0);
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
__blockintnumber =0;
dispatch_async(queue, ^{
number =100;
// 追加任务1
[NSThread sleepForTimeInterval:1];
// 模拟耗时操作
NSLog(@"1---%@",[NSThread currentThread]);
// 打印当前线程number =100;
dispatch_semaphore_signal(semaphore);
});
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
NSLog(@"end");
NSLog(@"number = %d",number);
}
输出结果:
2018-11-26 16:23:43.813788+0800 OC-Swift[6798:117982] <NSThread: 0x600001dd1400>{number = 1, name = main}
2018-11-26 16:23:43.813930+0800 OC-Swift[6798:117982] begin
2018-11-26 16:23:44.814834+0800 OC-Swift[6798:118028] 1---<NSThread: 0x600001da5640>{number = 3, name = (null)}
2018-11-26 16:23:44.815409+0800 OC-Swift[6798:117982] end
2018-11-26 16:23:44.815778+0800 OC-Swift[6798:117982] number = 100
结果分析:
这是因为异步执行不会做任何等待,可以继续执行任务。异步执行将任务1追加到队列之后,不做等待,接着执行dispatch_semaphore_wait方法。此时 semaphore == 0,当前线程进入等待状态。然后,异步任务1开始执行。任务1执行到dispatch_semaphore_signal之后,此时 semaphore == 1,dispatch_semaphore_wait方法使总信号量减1,正在被阻塞的线程(主线程)恢复继续执行。最后打印end,number = 100。这样就实现了线程同步,将异步执行任务转换为同步执行任务。
用GCD的信号量来实现异步线程同步操作
- (void)semaphore {
NSLog(@"%@",[NSThread currentThread]);
NSLog(@"begin");
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
dispatch_async(queue, ^{
NSLog(@"111===%@",[NSThread currentThread]);
dispatch_semaphore_signal(semaphore);
});
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
dispatch_async(queue, ^{
NSLog(@"222===%@",[NSThread currentThread]);
dispatch_semaphore_signal(semaphore);
});
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
dispatch_async(queue, ^{
NSLog(@"333===%@",[NSThread currentThread]);
dispatch_semaphore_signal(semaphore);
});
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
dispatch_async(dispatch_get_global_queue(0, 0), ^{
NSLog(@"444===%@",[NSThread currentThread]);
});
NSLog(@"end");
}
输出结果:
2018-11-26 16:38:38.125097+0800 OC-Swift[6970:124755] <NSThread: 0x6000020ca980>{number = 1, name = main}
2018-11-26 16:38:38.125197+0800 OC-Swift[6970:124755] begin
2018-11-26 16:38:38.125347+0800 OC-Swift[6970:124800] 111===<NSThread: 0x6000020446c0>{number = 4, name = (null)}
2018-11-26 16:38:38.125490+0800 OC-Swift[6970:124800] 222===<NSThread: 0x6000020446c0>{number = 4, name = (null)}
2018-11-26 16:38:38.125641+0800 OC-Swift[6970:125265] 333===<NSThread: 0x6000020b7f40>{number = 5, name = (null)}
2018-11-26 16:38:38.125735+0800 OC-Swift[6970:124755] end
2018-11-26 16:38:38.125763+0800 OC-Swift[6970:125265] 444===<NSThread: 0x6000020b7f40>{number = 5, name = (null)}
结果分析:
使用信号量实现异步线程同步操作时,虽然任务是一个接一个被同步执行的,但因为是在并发队列,并不是所有的任务都是在同一个线程执行的。这有别于异步函数+串行队列的方式(异步函数+ 串行队列的方式中,所有的任务都是在同一个新线程被串行执行的)。
后记:
- (void)groupSemaphore {
dispatch_group_t group = dispatch_group_create();
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
for(inti =0; i <10; i++)
{
dispatch_group_enter(group);
dispatch_group_async(group, queue, ^{
NSLog(@"%i",i);
dispatch_group_leave(group);
});
}
dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
NSLog(@"end");
}
输出结果:
2018-11-26 17:10:17.422095+0800 OC-Swift[7408:141478] 2
2018-11-26 17:10:17.422100+0800 OC-Swift[7408:141472] 0
2018-11-26 17:10:17.422103+0800 OC-Swift[7408:141477] 3
2018-11-26 17:10:17.422106+0800 OC-Swift[7408:141479] 1
2018-11-26 17:10:17.422280+0800 OC-Swift[7408:141479] 4
2018-11-26 17:10:17.422280+0800 OC-Swift[7408:141478] 5
2018-11-26 17:10:17.422286+0800 OC-Swift[7408:141472] 6
2018-11-26 17:10:17.422295+0800 OC-Swift[7408:141477] 7
2018-11-26 17:10:17.422354+0800 OC-Swift[7408:141479] 8
2018-11-26 17:10:17.422359+0800 OC-Swift[7408:141478] 9
2018-11-26 17:10:17.422801+0800 OC-Swift[7408:141430] end
- (void)groupSemaphore {
dispatch_group_t group = dispatch_group_create();
dispatch_semaphore_t semaphore = dispatch_semaphore_create(1);
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
for(inti =0; i <10; i++)
{
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
dispatch_group_async(group, queue, ^{
NSLog(@"%i",i);
dispatch_semaphore_signal(semaphore);
});
}
dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
NSLog(@"end");
}
输出结果:
2018-11-26 17:11:39.722899+0800 OC-Swift[7433:142403] 0
2018-11-26 17:11:39.723046+0800 OC-Swift[7433:142403] 1
2018-11-26 17:11:39.723149+0800 OC-Swift[7433:142403] 2
2018-11-26 17:11:39.723227+0800 OC-Swift[7433:142403] 3
2018-11-26 17:11:39.723304+0800 OC-Swift[7433:142403] 4
2018-11-26 17:11:39.723381+0800 OC-Swift[7433:142403] 5
2018-11-26 17:11:39.723465+0800 OC-Swift[7433:142404] 6
2018-11-26 17:11:39.723554+0800 OC-Swift[7433:142404] 7
2018-11-26 17:11:39.723637+0800 OC-Swift[7433:142404] 8
2018-11-26 17:11:39.723724+0800 OC-Swift[7433:142404] 9
2018-11-26 17:11:39.723799+0800 OC-Swift[7433:142371] end
两段代码结果对比,他们都确保了dispatch_group_wait最后执行,但是第一段是异步执行的,第二段是顺序执行的。dispatch_semaphore实现了异步线程同步操作。
网友评论