поведение dispatch_get_global_queue - PullRequest
27 голосов
/ 29 июля 2011

Следующий код:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
    for (int i=0; i<100000; i++) {
        NSLog(@"HIGH 1 %d", i);
    }
});
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{
    for (int i=0; i<100000; i++) {
        NSLog(@"LOW %d", i);
    }
});
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
    for (int i=0; i<100000; i++) {
        NSLog(@"HIGH 2 %d", i);
    }
});

приводит к смешению журналов высокого 1, высокого 2 и низкого.

Как получается, что он одновременно печатает журналы high1 и high2.Разве оба блога high1 и high2 не находятся в одной очереди?Так не должен ли блок high1 закончить перед началом выполнения блока high2?

Ответы [ 3 ]

22 голосов
/ 29 июля 2011

Это зависит от машины, на которой вы работаете. Я подозреваю, что вы запускаете это на своем Mac, потому что GCD автоматически создаст достаточно потоков для конкретной системы для заданий в глобальных очередях. Итак, у вас, вероятно, более одного ядра, поэтому GCD выполняет ваши задания на обоих ядрах.

Если вы создаете свою очередь, используя dispatch_queue_create, вы получаете последовательную очередь, и тогда вам гарантировано поведение FIFO.

FWIW (хотя вы не должны полагаться на это поведение), если вы запустите его на iPhone, я подозреваю, что вы увидите поведение последовательной очереди, потому что ваш iPhone одноядерный. Не надейтесь на это, хотя iPad 2 является многоядерным, я думаю!

РЕДАКТИРОВАТЬ:

Документация для dispatch_get_global_queue: Возвращает известную глобальную параллельную очередь с заданным уровнем приоритета.

6 голосов
/ 30 июля 2011

Вы только что проиллюстрировали, почему не следует вызывать методы, которые не являются поточно-ориентированными внутри dispatch_async. Если процессорных ядер достаточно для выполнения большего количества заданий, GCD продолжит работу и будет работать над ними независимо от того, вернулись ли предыдущие задания в заданной очереди. То же самое поведение может быть достигнуто в OS X 10.7, создавая ваши собственные очереди с:

dispatch_queue_create(NULL, DISPATCH_QUEUE_CONCURRENT);

Очевидно, что NSLog() можно вызывать так часто, как вы хотите, не беспокоясь о проблемах с ошибками доступа или подобных, но если вас беспокоит безопасность потоков или порядок возврата ваших заданий, рассмотрите возможность использования групп рассылки.

0 голосов
/ 15 ноября 2011

dispatch_get_global_queue является своего рода очередью параллелизма. Поскольку вы указываете одинаковый приоритет для high1 и high2, в результате получается сочетание high1 и high2. После этого это будет низкий результат, поскольку он имеет более низкий приоритет.

...