1、控制最大并发数
使用信号量可以设置最多有n条线程执行统一个任务,从而控制线程最大并发数:
- (instancetype)init {if (self = [super init]) {// 设置最大并发数5self.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]) {// 设置最大并发数1self.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;}
