Поведение dispatch_get_global_queue
Следующий код:
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 block finish, прежде чем запускать блок high2?
Ответы
Ответ 1
Это зависит от машины, на которой вы работаете. Я подозреваю, что вы используете это на своем Mac, потому что GCD автоматически создаст достаточно потоков для конкретной системы для заданий в глобальных очередях. Итак, у вас, вероятно, есть более одного ядра, поэтому GCD запускает ваши задания на обоих ядрах.
Если вы создаете свою очередь с помощью dispatch_queue_create
, вы получаете очередную очередь, и тогда вам гарантируется поведение FIFO.
FWIW (хотя вы не должны полагаться на это поведение), если вы запустите это на iPhone, я подозреваю, что вы увидите поведение последовательной очереди, потому что ваш iPhone одноядерный. Не полагайтесь на это, хотя iPad 2 является многоядерным, я думаю!
ИЗМЕНИТЬ:
Документация для dispatch_get_global_queue
:
Возвращает известную глобальную параллельную очередь заданного уровня приоритета.
Ответ 2
Вы только что проиллюстрировали, почему вы не должны вызывать методы, которые не являются потокобезопасными внутри dispatch_async
. Если для выполнения дополнительных заданий достаточно процессорных ядер, GCD продолжит работу и будет работать над ними, независимо от того, вернулись ли предыдущие задания в заданной очереди. Такое же поведение может быть достигнуто в OS X 10.7 путем создания собственных очередей с помощью:
dispatch_queue_create(NULL, DISPATCH_QUEUE_CONCURRENT);
Очевидно, что NSLog()
можно вызывать так часто, как вам нравится, не беспокоясь о том, что вы получаете плохие ошибки доступа или что-то подобное, но если вы обеспокоены потоковой безопасностью или порядком, в котором ваши возвращаемые задания учитывают использование групп отправки.
Ответ 3
dispatch_get_global_queue
является видом очереди concurrency. Если вы укажете тот же приоритет для high1 и high2, результатом будет сочетание high1 и high2. После этого это будет низкий результат, поскольку он имеет более низкий приоритет.