Параллельная очередь только с барьерной задачей

Недавно читаю коды популярной библиотеки кеширования изображений Зимородок.

Я не понимаю, как используется GCD на ImageDownloader. В этом загрузчике все операции, связанные с ImageFetchLoad (задача получения изображения), отправляются в параллельную очередь под названием barrierQueue:

barrierQueue = DispatchQueue(label: "com.onevcat.Kingfisher.ImageDownloader.Barrier.\(name)", attributes: .concurrent)

Запутанная часть заключается в том, что ВСЕ операции отправляются с использованием барьерной синхронизации:

barrierQueue.sync(flags: .barrier) {
    if let URL = task.internalTask.originalRequest?.url, let imageFetchLoad = self.fetchLoads[URL] {
        imageFetchLoad.downloadTaskCount -= 1
        if imageFetchLoad.downloadTaskCount == 0 {
            task.internalTask.cancel()
        }
    }
}

Каждая операция барьера будет блокировать друг друга, что делает очередь фактически последовательной. Так почему же Kingfisher использует очередь concurrent вместо serial?

Не думайте, что есть серьезная причина, когда это может быть просто история. Вы связались с разработчиком, который добавил флаг? (onevcat: github.com/onevcat/Kingfisher/commit/…) Особо обратите внимание, что до этого коммита некоторые использовали .barrier, а некоторые нет: github.com/onevcat/Kingfisher/blob/…

Rob Napier 30.03.2018 17:22

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

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

Ответы 1

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

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

Таким образом, в этих случаях вы можете использовать очередь concurrent, как это делает Kingfisher, и установить флаг .barrier для любых операций, которые изменяют состояние данных, чтобы сообщить блоку, чтобы он дождался завершения всех других операций в очереди перед выполнением.

Я не могу говорить о конкретном обосновании использования Kingfisher очереди concurrent, но просто хотел отметить пример использования, когда вы могли бы предпочесть concurrentserial для безопасности очереди GCD. Использование concurrent может обеспечить дополнительную гибкость, поскольку вы можете решить, должны ли операции выполняться одновременно или «последовательно» с флагом .barrier, в зависимости от поведения.

Описание этого шаблона можно найти в описании .barrier здесь: http://khanlou.com/2016/04/the-GCD-handbook/

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