简介:
1、常用函数及作用:
dispatch_semaphore_create(信号量值)用于创建信号量,参数:信号总量的初始值,如果小于0应该返回null
dispatch_semaphore_wait(信号量,等待时间)等待降低信号量,信号总量少于等于0会一直等待,否则就会正常执行,并让信号量-1,等待途中,信号总量变为大于0则,继续往下执行。该函数返回0表示得到通知,非0表示超时;详解:信号量大于零,则方法所在的线程会继续执行下边代码,然后信号量值减1,如果desema的值为零,则方法就会阻塞所在线程,一直等待,等到timeout,其所处的线程继续执行其后语句,如果在等待期间,信号量值加1,且此函数所在的线程获取了信号量,那么久继续执行下去并执行信号量减1.
dispatch_semaphore_signal(信号量) 会让信号总量加1,即通知信号,当返回值为0说明当前没有线程等待处理的信号量,其处理的信号量加1即可。当返回值不是0,说明有线程。
注:一般是先降低再增加,wait和signal成对使用。则报错:Thread x: EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP;没有wait只有signal则线程阻塞。
2、信号量的用途:
根据创建信号量总数的不同使创建信号量的作用也不同:
1》同步不同线程:dispatch_semaphore_create(0);任务块外wait,块里signal
dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
__block int j = 0;
dispatch_async(queue, ^{
j = 100;
dispatch_semaphore_signal(semaphore);
NSLog(@"sdsds:%@",[NSThread currentThread]);
});
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
在主线程按顺序执行,主线程执行到block时创建子线程,同时主线程运行到wait,因为总信号量为0,且超时设置我foever,所以主线程阻塞,同时block里发的子线程在继续执行到signal,执行完signal则信号总量为1,此时阻塞的主线程恢复继续执行,通过这种方式实现了,不同线程同步执行。
2》当做锁来使用:dispatch_semaphore_create(1); 任务block里先wait,再signal
dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
dispatch_semaphore_t semaphore = dispatch_semaphore_create(1);
for (int i = 0; i < 100; i++) {
dispatch_async(queue, ^{
// 相当于加锁
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
NSLog(@"i = %d semaphore = %@", i, semaphore);
// 相当于解锁
dispatch_semaphore_signal(semaphore);
NSLog(@"xcc:i = %d semaphore = %@", i, semaphore);
});
}
创建初始信号量值为1,然后进入任务block,先到用wait使总信号量减为0,然后是需要加锁的代码,然后再signal使用信号总量为1,因为wait后信号总量为零,当前线程阻塞,就不会有线程再进入到wait和signal之间的代码块,起到了锁的作用。
3》控制同时执行的线程数:dispatch_semaphore_create(n);n为常数
例如,现在有100张图片要下载。一般都会用开辟子线程的方式处理,但是因为是100张图片,我们不可能开100个线程处理,这样会导致占用内存过多,导致卡死,这时我们就要设定同时执行的线程数,保证下载效率的同时,又不卡。
假如我们开5条线程(一般,我们能接受的开辟子线程的数目就是5吧,毕竟每开一条要占用512k)
{
dispatch_semaphore_t semaphore = dispatch_semaphore_create(5);
dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
for (NSInteger index = 0; index < 5; index ++) {
dispatch_async(queue, ^{
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
NSLog(@"第%ld个任务",index);
sleep(2);
NSLog(@"第%ld个任务:%@",index,[NSThread currentThread]);
dispatch_semaphore_signal(semaphore);
NSLog(@"第%ld个任务完了",index);
});
}
}
demo地址:https://download.csdn.net/download/denggun12345/10737161