← Назад к вопросам

Что такое Serial?

1.0 Junior🔥 221 комментариев
#Многопоточность и асинхронность

Комментарии (1)

🐱
deepseek-v3.2PrepBro AI5 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Что такое Serial (Сериал)?

В контексте iOS-разработки под Serial (сокращение от Serial Queue — серийная очередь) чаще всего понимают механизм выполнения задач строго последовательно, одна за другой, в порядке их добавления. Это одно из фундаментальных понятий для работы с многопоточностью в рамках фреймворков Grand Central Dispatch (GCD) и Operation Queue.

Основная концепция

Serial Queue (серийная очередь) — это очередь задач (DispatchQueue), которая гарантирует, что следующая задача начнет выполняться только после полного завершения текущей. Это обеспечивает безопасный доступ к общим ресурсам (например, к переменной или файлу) из разных потоков, так как в любой момент времени с ресурсом работает не более одной задачи.

Ключевая противоположность серийной очереди — Concurrent Queue (конкурентная очередь), где задачи, добавленные в очередь, могут выполняться параллельно, если система имеет доступные потоки.

Пример создания и использования Serial Queue

import Foundation

// 1. Создание серийной очереди
let serialQueue = DispatchQueue(label: "com.example.serialQueue")

// 2. Переменная, доступ к которой нужно синхронизировать
var sharedCounter = 0

// 3. Асинхронное добавление нескольких задач в серийную очередь
serialQueue.async {
    for _ in 1...5 {
        sharedCounter += 1
        print("Задача 1: счетчик = \(sharedCounter) в потоке \(Thread.current)")
    }
}

serialQueue.async {
    for _ in 1...5 {
        sharedCounter += 10
        print("Задача 2: счетчик = \(sharedCounter) в потоке \(Thread.current)")
    }
}

// Даем время на выполнение асинхронных задач
sleep(1)
print("Итоговое значение счетчика: \(sharedCounter)")

Вывод (примерный, порядок гарантирован):

Задача 1: счетчик = 1 в потоке <NSThread: 0x...>{number = 7, name = (null)}
Задача 1: счетчик = 2 в потоке <NSThread: 0x...>{number = 7, name = (null)}
...
Задача 1: счетчик = 5 в потоке <NSThread: 0x...>{number = 7, name = (null)}
Задача 2: счетчик = 15 в потоке <NSThread: 0x...>{number = 8, name = (null)}
...
Задача 2: счетчик = 55 в потоке <NSThread: 0x...>{number = 8, name = (null)}
Итоговое значение счетчика: 55

Обратите внимание: Задача 2 начала выполняться только после полного завершения Задачи 1, несмотря на асинхронный вызов (async). Поток выполнения может измениться (с 7 на 8), но последовательность — нет.

Главные характеристики и применение

  • Синхронизация доступа: Это основное применение. Если несколько потоков пытаются изменить один объект, помещение всех операций записи в одну серийную очередь предотвращает состояние гонки (race condition).

  • Предсказуемость: Порядок выполнения задач строго соответствует порядку их добавления (FIFO — First-In-First-Out).

  • Deadlock (взаимная блокировка): С серийными очередями нужно быть осторожным. Синхронный вызов (sync) на текущей серийной очереди из той же очереди приведет к deadlock, так как задача будет ждать завершения самой себя.

    // Пример, приводящий к deadlock
    serialQueue.sync {
        // Этот блок никогда не начнет выполняться,
        // потому что очередь заблокирована внешним sync
        serialQueue.sync {
            print("Этот код никогда не выполнится")
        }
    }
    
  • Главная очередь (Main Queue): Самый важный пример серийной очереди в iOS — DispatchQueue.main. Все операции с UI обязательно должны выполняться на этой очереди, так как UIKit не является потокобезопасным.

    // Правильное обновление UI из фонового потока
    URLSession.shared.dataTask(with: url) { data, response, error in
        // Обработка данных в фоне
        let image = UIImage(data: data!)
    
        // Возвращаемся на главную очередь для обновления UI
        DispatchQueue.main.async {
            self.imageView.image = image
        }
    }.resume()
    

Serial Queue vs. Lock (Мьютекс)

Серийная очередь — это высокоуровневый, удобный и безопасный паттерн для синхронизации, альтернативный низкоуровневым примитивам вроде NSLock или pthread_mutex_t. Вместо того чтобы вручную блокировать и разблокировать доступ к ресурсу, вы просто ставите все операции с ним в одну серийную очередь. Система GCD управляет потоками за вас.

Заключение

Таким образом, Serial (Serial Queue) — это не просто "последовательный", а мощный инструмент для управления многопоточностью, обеспечивающий потокобезопасность (thread safety) и порядок выполнения. Понимание различий между серийными и конкурентными очередями, а также между асинхронными (async) и синхронными (sync) вызовами, является критически важным для написания стабильных, производительных и бездедлоковых iOS-приложений.

Что такое Serial? | PrepBro