Последовательная асинхронная очередь GCD против последовательной очереди синхронизации, вложенной в асинхронную

Мне нужно защитить критическую часть моего кода. Я не хочу, чтобы вызывающая сторона была заблокирована функцией, которая может занимать много времени, поэтому я создаю последовательную очередь с фоновым qos, а затем асинхронно отправляю:

private let someQueue = DispatchQueue(label: "\(type(of: self)).someQueue", qos: .background)

func doSomething() {
    self.someQueue.async { 
       //critical section
    }
}

Насколько я понимаю, функция будет напрямую возвращаться в вызывающий поток без блокировки. Я также видел где-то асинхронную отправку сначала в глобальную очередь, синхронно в последовательную очередь:

private let someQueue2 = DispatchQueue(label: "\(type(of: self)).someQueue2")

func doSomething() {
    DispatchQueue.global(qos: .background).async {
        self.someQueue2.sync { 
           //critical section
         }
    }
}

В чем разница между двумя подходами? Какой правильный подход?

Вторая форма кажется недоразумением того, кто не понимает, что локальная очередь отправки может быть сделана параллельной.

matt 18.12.2020 17:05

Вы никогда не должны вызывать dispatch_sync в параллельной очереди (которой является глобальная очередь), особенно когда продолжительность выполнения «критического раздела» может быть большой, поскольку это может привести к «взрыву потока». GCD был разработан таким образом, чтобы приложение создавало как можно меньше потоков. Итак, это на самом деле «антипаттерн». Итак, разница в том, что подход 1 является жизнеспособным, а подход 2 неправильным.

CouchDeveloper 20.12.2020 20:35

@CouchDeveloper Я согласен с вами, в устаревшей кодовой базе, над которой я работаю, первый подход используется во многих ситуациях, поэтому я сомневался в своем подходе.

laucel 21.12.2020 10:57
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
3
203
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

При первом подходе вызывающий поток не блокируется, и задача (критическая секция), переданная в асинхронном блоке, будет выполняться в фоновом режиме.

Во втором подходе вызывающий поток не блокируется, но «фоновый» поток будет ожидать выполнения блока синхронизации (критического раздела), который выполняется другим потоком.

Я не знаю, что вы делаете в своем критическом разделе, но кажется, что первый подход кажется лучшим. Обратите внимание, что фоновое qos довольно медленное, возможно, используйте qos по умолчанию для своей очереди, если вы не знаете, что делаете. Также обратите внимание, что соглашение требует, чтобы вы использовали идентификатор пакета в качестве метки для своей очереди. Что-то вроде этого:

private let someQueue = DispatchQueue(label: "\(Bundle.main.bundleIdentifier ?? "").\(type(of: self)).someQueue")

В моем критическом разделе я пишу журнал в файле, добавляя содержимое. Спасибо за ваше объяснение и предложение QOS, вы по-прежнему рекомендуете не использовать фон?

laucel 18.12.2020 20:12

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

Paulw11 18.12.2020 21:32

Другие вопросы по теме