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

Что такое Mutex?

1.7 Middle🔥 81 комментариев
#Многопоточность и асинхронность

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

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

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

Что такое Mutex (Взаимное исключение)?

Mutex (сокращение от mutual exclusion — взаимное исключение) — это примитив синхронизации, используемый в многопоточном программировании для защиты общих ресурсов от одновременного доступа несколькими потоками. Основная цель — предотвратить состояние гонки (race condition), когда результат выполнения программы зависит от непредсказуемого порядка выполнения потоков.

Основные принципы работы

Mutex работает по принципу «замка». Только один поток может владеть мьютексом в любой момент времени:

  • Поток захватывает (lock) мьютекс перед доступом к разделяемому ресурсу
  • Если мьютекс уже захвачен другим потоком, текущий поток блокируется до его освобождения
  • После завершения работы с ресурсом поток освобождает (unlock) мьютекс

Реализация в iOS/macOS

В iOS разработке вы чаще всего работаете с мьютексами через:

  • POSIX мьютексы из стандартной библиотеки C
  • Objective-C синхронизацию (@synchronized)
  • Grand Central Dispatch (GCD) очереди
  • NSLock и его варианты в Foundation
import Foundation

// Пример использования NSLock
class ThreadSafeCounter {
    private var count = 0
    private let lock = NSLock()
    
    func increment() {
        lock.lock()
        defer { lock.unlock() }
        count += 1
        print("Счетчик: \(count)")
    }
    
    func getCount() -> Int {
        lock.lock()
        defer { lock.unlock() }
        return count
    }
}

// Использование
let counter = ThreadSafeCounter()
DispatchQueue.concurrentPerform(iterations: 10) { _ in
    counter.increment()
}

Типы мьютексов

  1. Обычный мьютекс — базовый тип, повторная попытка захвата тем же потоком вызывает deadlock
  2. Рекурсивный мьютекс — позволяет одному потоку захватывать его несколько раз
  3. Читатель-писатель — оптимизация для сценариев «много читателей, мало писателей»

Проблемы и решения

Deadlock (взаимная блокировка) возникает, когда два или более потока ждут друг друга:

// Пример deadlock
let lockA = NSLock()
let lockB = NSLock()

DispatchQueue.global().async {
    lockA.lock()
    Thread.sleep(forTimeInterval: 0.1)
    lockB.lock() // Блокировка
    // Критическая секция
    lockB.unlock()
    lockA.unlock()
}

DispatchQueue.global().async {
    lockB.lock()
    Thread.sleep(forTimeInterval: 0.1)
    lockA.lock() // Блокировка
    // Критическая секция
    lockA.unlock()
    lockB.unlock()
}

Решения:

  • Всегда захватывать мьютексы в одинаковом порядке
  • Использовать таймауты для захвата
  • Применять более высокоуровневые абстракции (очереди GCD)

Сравнение с другими примитивами

  • Семафоры — позволяют ограниченному числу потоков доступ к ресурсу
  • Spinlock — активно опрашивает доступность вместо блокировки потока
  • Условные переменные — позволяют потокам ждать определенных условий

Практическое применение в iOS

  1. Защита структур данных — массивы, словари, счетчики
  2. Синхронизация доступа к файлам
  3. Защита кэшей — NSCache, пользовательские кэши
  4. Управление состоянием — флаги, статусы приложения

Best Practices

  • Держите критические секции короткими — минимизируйте время удержания мьютекса
  • Используйте defer в Swift для гарантированного освобождения
  • Избегайте вложенных блокировок — сложно отслеживать и дебажить
  • Предпочитайте GCD и Actor модель в современных Swift приложениях

Современные альтернативы в Swift

В Swift 5.5+ рекомендуется использовать Actor модель:

actor BankAccount {
    private var balance: Double = 0
    
    func deposit(amount: Double) {
        balance += amount
    }
    
    func withdraw(amount: Double) -> Bool {
        if balance >= amount {
            balance -= amount
            return true
        }
        return false
    }
}

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