如何使用dispatch_queue_set_specific()和dispatch_get_specific() [英] How to use dispatch_queue_set_specific() and dispatch_get_specific()

查看:177
本文介绍了如何使用dispatch_queue_set_specific()和dispatch_get_specific()的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我很难找到有关如何使用这些功能的良好示例.

I'm having a hard time finding good examples on how to use these functions.

static void * kQueue1Key = "key1";
static void * kQueue2Key = "key2";

dispatch_queue_t queue1 = dispatch_queue_create("com.company.queue1", DISPATCH_QUEUE_SERIAL);
dispatch_queue_t queue2 = dispatch_queue_create("com.company.queue2", DISPATCH_QUEUE_SERIAL);

dispatch_queue_set_specific(queue1, kQueue1Key, (void *)kQueue1Key, NULL);
dispatch_queue_set_specific(queue2, kQueue2Key, (void *)kQueue2Key, NULL);

dispatch_sync(queue1, ^{
    if(dispatch_get_specific(kQueue1Key))
    {
        NSLog(@"I'm expecting this line to run (A)");

        dispatch_sync(queue2, ^{

            NSLog(@"I'm expecting this line to run (B)");

            if(dispatch_get_specific(kQueue2Key))
            {
                if(dispatch_get_specific(kQueue1Key))
                {
                    NSLog(@"I'm expecting this line to run (C)");
                }
                else
                {
                    [NSException raise:NSInternalInconsistencyException format:@"Should not end up here (C)"];
                }
            }
            else
            {
                [NSException raise:NSInternalInconsistencyException format:@"Should not end up here (B)"];
            }
        });
    }
    else
    {
        [NSException raise:NSInternalInconsistencyException format:@"Should not end up here (A)"];
    }
});

结果

I'm expecting this line to run (A)
I'm expecting this line to run (B)
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Should not end up here (C)'

这是预期的行为吗?如果由于不在队列中而将dispatch_sync分配到queue1,则将导致死锁.我想念什么?

Is it expected behavior? If I were to dispatch_sync to queue1 since I'm not on the queue I would deadlock. What am I missing?

推荐答案

哦,在这里,为什么要得到你要得到的东西突然出现在我的脑海中.注意事项:

Oh here, it popped into my head why you're getting what you're getting. Notes in line:

dispatch_sync(queue1, ^{

到此为止,当前队列"为queue1

When you get to this point, the "current queue" is queue1

    if(dispatch_get_specific(kQueue1Key))

您正在向当前队列询问它为kQueue1Key所具有的值,因此您将其设置得较早,以便将其返回给您.

You're asking the current queue for the value it has for kQueue1Key, you set that earlier, so it gives it back to you.

    {
        NSLog(@"I'm expecting this line to run (A)");

        dispatch_sync(queue2, ^{

到此为止,当前队列"现在为queue2

When you get to this point, the "current queue" is now queue2

            NSLog(@"I'm expecting this line to run (B)");

            if(dispatch_get_specific(kQueue2Key))

您正在向当前队列询问它为kQueue2Key所具有的值,因此您将其设置得较早,以便将其返回给您.

You're asking the current queue for the value it has for kQueue2Key, you set that earlier, so it gives it back to you.

            {

                if(dispatch_get_specific(kQueue1Key))

您现在正在向当前队列询问kQueue1Key的值.由于当前队列为queue2,并且您从未在queue2上使用kQueue1Key设置值,所以您会返回NULL.

You're now asking the current queue for the value it has for kQueue1Key. Since the current queue is queue2 and you never set a value with kQueue1Key on queue2 you get back NULL.

                {
                    NSLog(@"I'm expecting this line to run (C)");
                }
                else
                {
                    [NSException raise:NSInternalInconsistencyException format:@"Should not end up here (C)"];
                }

此处的误解是dispatch_get_specific不会遍历嵌套队列的 stack ,而是会遍历队列定位血统.例如,如果您改为 this

The misunderstanding here is that dispatch_get_specific doesn't traverse the stack of nested queues, it traverses the queue targeting lineage. For instance, if you did this instead,

static void * kQueue1Key = (void*)"key1";
static void * kQueue2Key = (void*)"key2";

dispatch_queue_t queue1 = dispatch_queue_create("com.company.queue1", DISPATCH_QUEUE_SERIAL);
dispatch_queue_t queue2 = dispatch_queue_create("com.company.queue2", DISPATCH_QUEUE_SERIAL);

dispatch_queue_set_specific(queue1, kQueue1Key, (void *)kQueue1Key, NULL);
dispatch_queue_set_specific(queue2, kQueue2Key, (void *)kQueue2Key, NULL);

// Set Queue2 to target Queue1
dispatch_set_target_queue(queue2, queue1);

dispatch_sync(queue2, ^{

    if(dispatch_get_specific(kQueue1Key))
    {
        NSLog(@"I'm expecting this line to run (A)");
    }
    else
    {
        [NSException raise:NSInternalInconsistencyException format:@"Should not end up here (C)"];
    }

    if(dispatch_get_specific(kQueue2Key))
    {
        NSLog(@"I'm expecting this line to run (B)");
    }
    else
    {
        [NSException raise:NSInternalInconsistencyException format:@"Should not end up here (C)"];
    }
});

...定位关系是遍历的关系,而不是堆栈关系.如果有一些遍历堆栈关系的东西会很好,但是我什么都不知道(您不必自己实现).

...the targeting relationship is the one that gets traversed, not the stack relationship. It would be nice if there were something that traversed the stack relationship, but I'm not aware of anything (that you wouldn't have to implement yourself).

这篇关于如何使用dispatch_queue_set_specific()和dispatch_get_specific()的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆