3

Я новичок в разработке iPhone и перехожу к концепции GCD для многопоточности.dispatch_queue_t является последовательной очередью, то почему она существует даже в концепции с несколькими задачами?

'dispatch_queue_t' создает последовательную очередь, и я прочитал, что последовательная очередь будет выполнять только одно задание за раз. GCD предназначен для одновременного выполнения нескольких задач, то почему существует очередная очередь?

Например, я хочу выполнить 2 задачи. Задача A и задача B. Я создаю одну последовательную очередь для выполнения обеих этих задач. Я делаю это в главной очереди. Вот код, что я делаю:

dispatch_queue_t my_serial_queue = dispatch_queue_create("queue_identifier", 0); 

    dispatch_sync(my_serial_queue, ^{ 
     NSLog(@"Task 1"); 
    }); 

    dispatch_sync(my_serial_queue, ^{ 
     NSLog(@"Task 2"); 
    }); 

Теперь, в соответствии с правилом, и задача будет выполняться последовательно, как это последовательная очередь т.е. Задача A выполняется первым, а затем после Задача A завершена, задача B будет выполнен. А также он дает мне тот же результат в журнале.

Итак, мой вопрос: что, если я хочу выполнять обе задачи одновременно? Если ответ на этот вопрос, чтобы создать другую серийную очередь для задания В то код должен быть структурирована следующим образом:

dispatch_queue_t my_serial_queue_1 = dispatch_queue_create("queue_identifier_1", 0); 
dispatch_queue_t my_serial_queue_2 = dispatch_queue_create("queue_identifier_2", 0); 


    dispatch_sync(my_serial_queue_1, ^{ 
     NSLog(@"Task 1"); 
    }); 

    dispatch_sync(my_serial_queue_2, ^{ 
     NSLog(@"Task 2"); 
    }); 

Я получаю тот же результат. Причина в том, что я использую вызов «dispatch_sync» вместо вызова «dispatch_async». Но поскольку я выполняю обе задачи в разных очередях, они не должны выполняться одновременно? Если нет, то почему мы должны создавать другую очередь? Возможно, я использовал одну и ту же очередь для вызова «dispatch_async» для одновременного выполнения обеих задач.

Мне действительно нужен ответ на этот вопрос, потому что, прежде чем проектировать структуру моих многозадачных приложений в будущем, это поможет мне лучше.

Цените свой совет. Заранее спасибо.

ответ

4

Ваше замешательство полностью связано с тем, что вы используете dispatch_sync. dispatch_sync - это не инструмент для получения параллельного исполнения, это инструмент для временного ограничения его безопасности.

Как только вы используете dispatch_async, вы можете получить параллелизм либо с несколькими очередями, либо с помощью параллельных очередей. Цель использования последовательных очередей в этом контексте - управление, работа которого выполняется одновременно.

Рассмотрим следующий пример очень глупый:

__block void *shared = NULL; 
for (;;) { 
    dispatch_async(aConcurrentDispatchQueue, ^{ 
     shared = malloc(128); 
     free(shared); 
    } 
} 

это произойдет сбой, поскольку в конечном итоге, два из параллельно выполняемыми блоков освободит «общий» в строке. Это надуманный пример, но на практике почти все разделяемые переменные состояния не должны меняться одновременно. Серийные очереди - это ваш инструмент для обеспечения того, чтобы вы это делали.

Сведение:

  • Когда работа в ваших блоках действительно независима и потокобезопасный, и чисто вычислительная, идти вперед и использовать dispatch_async к одновременному очереди
  • Если у вас есть логически независимые задачи, которые каждый состоят из нескольких связанных блоков, используют последовательную очередь для каждой задачи.
  • Когда у вас есть работа, которая обращается к общему изменяемому состоянию, выполните эти обращения в блоках dispatch_sync() ed в последовательной очереди, а остальная часть работы в параллельной очереди
  • Когда вам нужно сделать пользовательский интерфейс, связанные с работой, dispatch_async или dispatch_sync в основную очередь, в зависимости от того, нужно ли ждать его, чтобы закончить или не
+1

@ Catfish_Man: Короче говоря, если я хочу выполнить 2 задачи (те, о которых я упоминал) полностью, я либо должен (1) использовать 'dispatch_async' в последовательной очереди, либо (2) создать 2 параллельные очереди для этих 2 задач вместо создания 2 очередей 'dispatch_queue_t' (потому что 'dispatch_queue_t' создает очередность). – NSPratik

+0

@ Catfish_Man: Предположим, что эти 2 задания полностью независимы. – NSPratik

+0

Одна параллельная очередь или две последовательные очереди. Последовательные очереди упорядочивают все на них, но одновременно с каждой очередью. Одновременные очереди не заказывают на них все. –

1

«dispatch_queue_t» ничего не создает. dispatch_queue_t - очередь отправки, последовательная или параллельная.

dispatch_queue_create имеет два параметра. Второй параметр определяет, будет ли создаваемая очередь последовательной или параллельной очередью. Но обычно вы не создаете параллельные очереди самостоятельно, а используете одну из трех существующих параллельных очередей.

dispatch_sync отправляет блок в очередь и ждет, пока блок не закончен. Должно быть очевидно, что это очень ограничивает параллелизм. Вы должны почти всегда использовать dispatch_async.

Последовательные очереди могут выполнять только один блок за раз. Должно быть очевидно, что это очень ограничивает параллелизм. Последовательные очереди по-прежнему полезны, когда вам нужно выполнять разные блоки один за другим, и они могут выполняться одновременно с блоками в других очередях.

Так что для максимального использования процессоров используйте dispatch_async в параллельной очереди. И нет необходимости создавать несколько параллельных очередей. Это одновременно. Он может запускать любое количество блоков одновременно.

+0

@ gnasher729: Вы заявляете: «Последовательные очереди по-прежнему полезны, когда вам нужно выполнять разные блоки один за другим, и они могут выполняться одновременно с блоками в других очередях». Чтобы сделать его практичным, я создал демоверсию, создав две последовательные очереди. Но эти очереди не выполняются одновременно. Блоки очереди B не выполняются до тех пор, пока все блоки из A не завершит выполнение. Я даже попытался сделать обе эти очереди параллельными, но я получил тот же результат. Почему эти очереди не могут выполняться одновременно, пока я не вызову dispatch_async? (Даже я создаю параллельную очередь) – NSPratik

+1

Если вы используете dispatch_sync (первый блок), dispatch_sync (второй блок), то сам dispatch_sync ждет, пока первый блок не будет завершен, а dispatch_sync (второй блок) будет выполняться только после завершения первого блока. Если вы используете его так, это не имеет большого значения, что делают очереди. – gnasher729