1、控制最大并发数
使用信号量可以设置最多有n条线程执行统一个任务,从而控制线程最大并发数:
- (instancetype)init {
if (self = [super init]) {
// 设置最大并发数5
self.semaphore = dispatch_semaphore_create(5);
}
return self;
}
- (void)otherTest {
for (int i = 0; i < 20; i++) {
[[[NSThread alloc] initWithTarget:self selector:@selector(test) object:nil] start];
}
}
// 控制最大并发数
- (void)test {
// 开始等待
dispatch_semaphore_wait(self.semaphore, DISPATCH_TIME_FOREVER);
sleep(2);
NSLog(@"%s - %@",__func__, [NSThread currentThread]);
// 等待结束
dispatch_semaphore_signal(self.semaphore);
}
2、信号量控制过程
wait方法:
dispatch_semaphore_wait(self.semaphore, DISPATCH_TIME_FOREVER);
如果信号量的值 > 0,就让信号量的值减1,然后继续往下执行代码。
如果信号量饿值 <= 0,就会休眠等待,直到信号量的值大于零(等待时间由传入的时间参数决定),就让信号量的值减1,然后继续往下执行代码。
signal方法:
dispatch_semaphore_signal(self.semaphore);
3、线程同步
如果将信号量的值设置为1,那么信号量也可以解决线程同步问题,保证同一时间只有一个线程执行任务:
- (instancetype)init {
if (self = [super init]) {
// 设置最大并发数1
self.ticketSemaphore = dispatch_semaphore_create(1);
}
return self;
}
// 线程同步
- (void)__saleTicket {
dispatch_semaphore_wait(self.ticketSemaphore, DISPATCH_TIME_FOREVER);
[super __saleTicket];
dispatch_semaphore_signal(self.ticketSemaphore);
}
4、使用技巧
想要保证每个方法有一个信号量控制,可以在方法内部创建静态变量。
- (void)test {
static dispatch_semaphore_t semaphore;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
semaphore = dispatch_semaphore_create(1);
});
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
// ......
dispatch_semaphore_signal(semaphore);
}
还可以把开始和结束宏定义,减少重复代码量:
// 开始并等待
#define SemaphonreBegin \
static dispatch_semaphore_t semaphore; \
static dispatch_once_t onceToken; \
dispatch_once(&onceToken, ^{ \
semaphore = dispatch_semaphore_create(1); \
}); \
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
// 结束
#define SemaphonreEnd \
dispatch_semaphore_signal(semaphore);
// 调用方法
- (void)test3 {
SemaphonreBegin;
// ......
SemaphonreEnd;
}