ios开发GCD的dispatch_semaphore

简介:

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

     

猜你喜欢

转载自blog.csdn.net/denggun12345/article/details/83268800