GCD篇

dispatch_semaphore(信号量)

  • 语法解析
//初始化信号量
* dispatch_semaphore_t dispatch_semaphore_create(long value) 
/*接收一个信号和时间值,若信号量为0,则阻塞当前线程,当信号量大于0或经过输入的时间值,
若信号量大于0,则会使信号量减1,程序继续往下执行。
*/
* long dispatch_semaphore_wait(dispatch_semaphore_t dsmea, dispatch_time_t timeout) 
//使信号量加1并返回
* long dispatch_semaphore_signal(dispatch_semaphore_t dsmea)
  • 保持线程同步
dispatch_queue_t queue = dispatch_get_global_queue(0,0);
dispatch_semaphore_t semaphore = dispatch_semaphore_creat(0);
__block int j = 0;
dispatch_async(queue, ^{
  j = 100;
  dispatch_semaphore_signal(semaphore);
});
dispatch_semaphore_wait(semaphere, DISPATCH_TIME_FOREVER);
//此时打印j的值为100,如果去掉dispatch_semaphore_signal(semaphore);打印的值为0.
  • 为线程加锁
dispatch_queue_t queue = dispatch_get_global_queue(0,0);
dispatch_semaphore_t semaphore = dispatch_semaphore_create(1);
for(NSInteger i = 0; i< 100 ; i++){
  dispatch_semaphore_wait(semaphore,DISPATCH_TIME_FOREVER);
  NSLog("i = %zd semaphore- %@",i , semaphore);
  dispatch_semaphore_signal(semaphore);
}
//顺序遍历for循环,执行100次。

宏定义

#ifndef dispatch_queue_async_safe
#define dispatch_queue_async_safe(queue,blcok)
if(dispatch_queue_get_label(DISPATCH_CURRENT_QUEUE_LABEL) == dispatch_queue_get_label(queue)){
  block()
}else{
  dispatch_async(queue,blcok);
}
#endif

#ifndef dispatch_main_async_safe
#define dispatch_main_async_safe(block)  
  dispatch_queue_async_safe(dispatch_get_main_queue, block);
#endif

dispatch_sync 与dispatch_async

  • dispatch_sync
    主要用于代码上下文对时序有强要求的场景。
__block UIImage *image;
dispatch_sync_on_main_queue(^{
  image = [UIImage imageNamed@"Resource/image"];
});
attachment.image = image;

1.为什么会死锁?

当前代码在queue0中执行,我们调用dispath_sync 将一个任务block1 扔到queue0中执行,会导致死锁。
//当前queue0中执行block0时,把一个block1 dispatch_sync 扔到queue0中,block0在执行一半的时候,需要等待自己的下一个任务block1执行完才能执行,而block1在等block0执行完才执行,构成死锁。

2.安全方法

 static inline void dispatch_sync_on_main_queue(void(^block)()){
  if(pthread_main_np()){
    block();
  }else{
    dispatch_sync(dispatch_get_main_queue,block());
  }
}

你可能感兴趣的:(GCD篇)