GCD全局并发队列并不总是并发(iOS设备)?

时间:2011-11-23 08:58:56

标签: ios concurrency grand-central-dispatch

在iOS设备上,我最近发现了一种奇怪的行为。

代码1:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        NSLog(@"1111");
    });
    while (1) {
        sleep(1);
    }
});

代码2:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        NSLog(@"1111");
    });
    while (1) {
        sleep(0.5);
    }
});

Code1和Code2唯一的区别是Code1每个循环休眠1秒,Code2休眠0.5。

如果您在具有单核的iOS设备上运行这两个代码,Code1将打印出@“1111”,但Code2将不打印。

我不是为什么,假设全局队列是并发的。无论其他块正在做什么,都应该打印出数字。如果它是由于单个核心设备的限制,为什么睡眠(0.5)和睡眠(1)会有所不同?

我真的想知道原因。

修改 我发现使用sleep(0.5)是我的愚蠢错误。 sleep()函数采用unsigned int参数。所以sleep(0.5)等于sleep(0)。但是sleep(0)会阻塞整个并发队列吗?

2 个答案:

答案 0 :(得分:3)

原因是你的第二个sleep()本质上是一个sleep(0),这意味着你现在正在对GCD给你的线程进行buzz循环,这可能与执行嵌套dispatch_async的线程相同()如果你有机会做任何其他事情,这是第一个例子。在一秒睡眠期间,GCD看到线程被阻塞并创建一个新线程来为未完成的排队请求提供服务。在第二个例子中,你基本上在计算上使得排队的工作挨饿 - GCD不够聪明,不知道一个线程被锁定在一个无限循环中,而你没有给系统足够的工作来证明(在GCD的眼中)创建另一个线程,所以......我基本上发现了GCD工作逻辑低阈值的错误。

答案 1 :(得分:0)

刚签出,第1和第2个片段打印“1111”。 注意,您使用的dispatch_async的嵌套不会带来任何利润,因为您设置了相同的优先级(DISPATCH_QUEUE_PRIORITY_DEFAULT)所有任务“NSLog(@"1111");

和“

while (1) {
        sleep(0.5);

将添加到同一目标队列中。结果我可以假设在第一种情况下,首先执行带有WHILE的块,并且因为它永远不会完成,所以队列中的下一个任务(NSLog(...))将永远不会被调用。

您可以尝试为队列使用不同的优先级(DISPATCH_QUEUE_PRIORITY_LOW f.e。)。