Swift Utilities — Потокобезопасное свойство

Моя цель - предложение широкого ассортимента товаров и услуг на постоянно высоком качестве обслуживания по самым выгодным ценам.

За годы работы разработчиком iOS, я собрал множество инструментов и полезных штук, которые облегчают процесс разработки. В этой статье, я хочу поделиться одним из таких инструментов. Это будет не большая статья. Я покажу, как пользоваться этой утилитой, продемонстрирую её в действии. Надеюсь, что статья окажется полезной для вас.

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

@SynchronizedLock – это свойство-обёртка в Swift, обеспечивающая потокобезопасный доступ к переменной. Это означает, что при чтении и записи значения обёрнутой переменной, эти операции будут безопасно выполняться в разных потоках.

/// When using this property wrapper, you can ensure that reads and writes to the wrapped value are thread-safe.
/// Example:
///
///```swift
/// class SomeClass {
///     @SynchronizedLock var count: Int = 0
///
///     func main() {
///         DispatchQueue.global().async {
///             for _ in 1 ... 1000 {
///                 count += 1
///             }
///         }
///         DispatchQueue.global().async {
///             for _ in 1 ... 1000 {
///                 count += 1
///             }
///         }
///     }
///```
@propertyWrapper
public struct SynchronizedLock<Value> {
    private var value: Value
    private var lock = NSLock()

    public var wrappedValue: Value {
        get { lock.synchronized { value } }
        set { lock.synchronized { value = newValue } }
    }

    public init(wrappedValue value: Value) {
        self.value = value
    }
}

private extension NSLock {

    @discardableResult
    func synchronized<T>(_ block: () -> T) -> T {
        lock()
        defer { unlock() }
        return block()
    }
}

Как это работает?

Для обеспечения потокобезопасности, @SynchronizedLock использует NSLock. Это обеспечивает, что только один поток может доступаться к переменной в данный момент времени. Блокировка освобождается только после завершения операции, позволяя следующему потоку войти в критическую секцию.

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

Рассмотрим класс SomeClass, где мы используем @SynchronizedLock для потокобезопасного доступа к переменной count.

class SomeClass {
    @SynchronizedLock var count: Int = 0

    func main() {
        DispatchQueue.global().async {
            for _ in 1 ... 1000 {
                self.count += 1
            }
        }
        DispatchQueue.global().async {
            for _ in 1 ... 1000 {
                self.count += 1
            }
        }
    }
}

В этом примере, два разных потока пытаются изменить значение count одновременно. Благодаря @SynchronizedLock, операции инкремента выполняются без конфликтов и состояние гонки.

Преимущества и ограничения

Основное преимущество @SynchronizedLock заключается в простоте использования и обеспечении безопасности данных в многопоточной среде. Однако использование блокировок может привести к снижению производительности, если они используются чрезмерно или в неоптимальном контексте.

Еще статьи Swift Utilities:

  • Swift Utilities — Работа с Динамическими Цветами

  • Swift Utilities — Упрощаем работу с UserDefaults

  • Swift Utilities — Equitable для сложных Enum

Источник: https://habr.com/ru/articles/774890/


Интересные статьи

Интересные статьи

Apple представила совершенно новый фреймворк CoreTransferable и ShareLink вью в SwiftUI, позволив нам совместно использовать контент и экспортировать его из наших приложений весьма...
В 2021 году на просторах интернета случайно увидел Sber на geecko.com, тогда компания Sber проводила fight типа "староверы" против "новокодеров". (Простите за неточности, вспоминаю по памяти.)И когда ...
Данная статья поможет вам создать свой первый Swift Package. Мы воспользуемся популярной C++ библиотекой для линейной алгебры Eigen, чтобы продемонстрировать, как можно о...
Привет! Меня зовут Антон, я iOS-разработчик в Joom. Из этой статьи вы узнаете, как мы работаем с DI-фреймворком Needle, и реально ли он чем-то выгодно отличается от аналогичных решени...
Представим, нам нужно внести небольшую правку в работу экрана. Экран меняется каждую секунду, поскольку в нем одновременно происходит множество процессов. Как правило, чтобы урегу...