编写高质量代码的52个有效方法

52个有效方法(46) - 不要使用dispatch_get_c

2018-10-04  本文已影响14人  SkyMing一C
可重入
dispatch_get_current_queue

使用GCD的时候经常要判断当前代码是在哪个队列上执行的,会发现有下面这个函数:

 dispatch_queue_t dispatch_get_current_queue();

iOS 6.0开始已经弃用这个函数了,它检测当前队列是不是某个特定的队列。但在使用dispatch_get_current_queue来判断是否当前线程返回的可能不是你想要的结果。

-(void)demo1{
    dispatch_queue_t queueA = dispatch_queue_create("com.lyk.queueA", NULL);
    dispatch_queue_t queueB = dispatch_queue_create("com.lyk.queueB", NULL);
    
    dispatch_sync(queueA, ^{
       dispatch_sync(queueB, ^{
          dispatch_sync(queueA, ^{
             //......
          });
       });
    });
}
-(void)demo2{
    dispatch_queue_t queueA = dispatch_queue_create("com.sky.queueA", NULL);
    dispatch_queue_t queueB = dispatch_queue_create("com.sky.queueB", NULL);
    
    dispatch_sync(queueA, ^{
        dispatch_sync(queueB, ^{
            dispatch_block_t block = ^{};
            if (dispatch_get_current_queue() == queueA) {
                block();
            } else {
                dispatch_sync(queueA, block);
            }
        });
    });
}


GCD方法可重入
 dispatch_queue_t queueA = dispatch_queue_create("com.sky.queueA", NULL);
    dispatch_queue_t queueB = dispatch_queue_create("com.sky.queueB", NULL);
    dispatch_set_target_queue(queueB, queueA);
   
    static int specificKey;
    CFStringRef specificValue = CFSTR("queueA");
    dispatch_queue_set_specific(queueA,
                                &specificKey,
                                (void*)specificValue,
                                (dispatch_function_t)CFRelease);
   
    dispatch_sync(queueB, ^{
        dispatch_block_t block = ^{
                //do something
        };
        CFStringRef retrievedValue = dispatch_get_specific(&specificKey);
        if (retrievedValue) {
            block();
        } else {
            dispatch_sync(queueA, block);
        }
    });
void dispatch_reentrant(void (^block)())
{
    static NSRecursiveLock *lock = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        lock = [[NSRecursiveLock alloc]init];
    });
    [lock lock];
    block();
    [lock unlock];
}
 
    dispatch_queue_t queueA = dispatch_queue_create("com.yiyaaixuexi.queueA", NULL);
    dispatch_block_t block = ^{
         //do something
    };
    dispatch_sync(queueA, ^{
        dispatch_reentrant(block);
    }); 
要点
  1. dispatch_get_current_queue函数的行为常常与开发者所预期的不同。此函数已经废弃,只应做调试使用。

  2. 由于派发队列是按层级来组织的,所以无法单用某个队列对象来描述“当前队列”这一概念。

  3. dispatch_get_current_queue函数用于解决由不可重入的代码所引发的死锁,然而能用此函数解决的问题,通常也能改用“队列特定数据”来解决。

上一篇 下一篇

猜你喜欢

热点阅读