被废弃的dispatch_get_current_queue

原创 2014年01月02日 11:23:39

      

想说说被废弃的dispatch_get_current_queue,不得不提一个概念:可重入。

        什么是可重入,来自维基百科:若一个程序或子程序可以“安全的被并行执行(Parallel computing)”,则称其为可重入(reentrant或re-entrant)的。

即当该子程序正在运行时,可以再次进入并执行它(并行执行时,个别的执行结果,都符合设计时的预期)。
     

若一个函数是可重入的,则该函数:

  • 不能含有静态(全局)非常量数据
  • 不能返回静态(全局)非常量数据的地址
  • 只能处理由调用者提供的数据
  • 不能依赖于单实例模式资源的锁
  • 不能调用(call)不可重入的函数(有呼叫(call)到的函数需满足前述条件)

       有时候我们很希望知道当前执行的queue是谁,比如UI操作需要放在main queue中执行。如果可以知道当前工作的queue是谁,就可以很方便的指定一段代码操作在特定的queue中执行。 dispatch_get_current_queue() 正好能帮上忙。于是乎,在指定的queue中做一些操作,就可以非常清晰的实现:

       

void func(dispatch_queue_t queue, dispatch_block_t block)
{
    if (dispatch_get_current_queue() == queue) {
        block();
    }else{
        dispatch_sync(queue, block);
    }
}

然后潜意识里,觉得这个函数是可重入的。

但当target queue恰好是current queue时,同步阻塞会导致死锁。

- (void)deadLockFunc
{
    dispatch_queue_t queueA = dispatch_queue_create("com.yiyaaixuexi.queueA", NULL);
    dispatch_queue_t queueB = dispatch_queue_create("com.yiyaaixuexi.queueB", NULL);
    dispatch_sync(queueA, ^{
        dispatch_sync(queueB, ^{
            dispatch_block_t block = ^{
                //do something
            };
            func(queueA, block);
        });
    });
}



问题出在GCD队列本身是不可重入的,串行同步队列的层级关系,是出现问题的根本原因。
为了防止类似的误用,苹果在iOS6废弃了dispatch_get_current_queue()方法。强大的dispatch_get_current_queue()也只能当作一个调试工具了。


那么应该如何保证GCD方法可重入呢?
  • dispatch_queue_set_specific 标记队列
  • 递归锁

分别给出两种方法的示例代码片段:

1)dispatch_queue_set_specific

 dispatch_queue_t queueA = dispatch_queue_create("com.yiyaaixuexi.queueA", NULL);
    dispatch_queue_t queueB = dispatch_queue_create("com.yiyaaixuexi.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);
        }
    });



2)递归锁

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);
    }); 






版权声明:本文为博主原创文章,未经博主允许不得转载。

GCD 被弃方法dispatch_get_current_queue

想说说被废弃的dispatch_get_current_queue,不得不提一个概念:可重入。         什么是可重入,来自维基百科:若一个程序或子程序可以“安全的被并行执行(Parallel...
  • u011374880
  • u011374880
  • 2015年01月15日 17:54
  • 805

被废弃的dispatch_get_current_queue

转自 http://blog.csdn.net/yiyaaixuexi/article/details/17752925?ticket=st-95524-cdycl4kwpntefcrbnbsh-pa...
  • ssyyjj88
  • ssyyjj88
  • 2016年03月29日 12:23
  • 524

写高质量OC代码52建议总结:46.不要使用dispatch_get_current_queue

使用GCD的时候经常要判断当前代码是在哪个队列上执行的,会发现有下面这个函数:  dispatch_queue_t dispatch_get_current_queue();  iOS 6.0开始...
  • viiimaus
  • viiimaus
  • 2017年07月27日 10:01
  • 536

vue2.0子组件向父组件传递数据(饿了么例子)vue2.0废弃$dispatch,替换成$emit 和$refs

vue2.0废弃$dispatch,替换成$emit 和$refs,使用方法如下(根据慕课饿了么案例,教程上的写法要改[为了购物车小球抛下的动画]): // good...
  • wenjiusui8083
  • wenjiusui8083
  • 2017年12月19日 14:46
  • 281

告诉你dispatch_queue_set_specific和dispatch_get_specific是个什么鬼

dispatch_queue_set_specific就是向指定队列里面设置一个表示 如: dispatch_queue_set_specific(queue1, queueKey1, &queueK...
  • Mr_yong
  • Mr_yong
  • 2016年02月19日 14:37
  • 9303

iOS学习笔记5-GCDAsyncUdpSocket中的dispatch_queue_set_specific

用到GCDAsyncUdpSocket开源库的时候,发现了这个函数: dispatch_queue_set_specific,于是做下笔记。...
  • xiaoluodecai
  • xiaoluodecai
  • 2015年08月02日 22:27
  • 2516

IOS对于线程队列的一些理解

第一部分:线程与队列 线程是代码执行的路径,队列则是用于保存以及管理任务的,线程负责去队列中取任务进行执行。 例如:在主线程调用如下代码 dispatch_sync(queue, ^{      ...
  • jacky_jin
  • jacky_jin
  • 2017年03月30日 15:59
  • 1366

被废弃的dispatch_get_current_queue

苹果为何废弃dispatch_get_current_queue
  • yiyaaixuexi
  • yiyaaixuexi
  • 2014年01月02日 11:23
  • 31227

GCD之死锁

GCD相当好用,但用不好就会死锁,始终要记着这样一句秘籍: 不要在串行队列放dispatch_sync、dispatch_apply 下面看几个例子 1 ...
  • wuji3390
  • wuji3390
  • 2017年04月28日 20:52
  • 47

dispatch_get_current_queue 废弃

由于iOS7以后 dispatch_get_current_queue 被废弃,所以需要寻找一个替代的方案。 发现 dispatch_get_current_queue 并没有字面上那么简单。 这个函...
  • wihing
  • wihing
  • 2013年08月01日 13:42
  • 5293
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:被废弃的dispatch_get_current_queue
举报原因:
原因补充:

(最多只允许输入30个字)