iOS Interview - Is static var thread-safe?

May 30, 20243 min read#swift, #concurrency, #ios, #interview

Is static var thread-safe?

I have recently got this question in an interview.

Is the following code thread safe?

class Solution {
    static var names: [Int] = []
}

Let’s analyse the code a bit to answer it:

  • The names variable is defined as a static property in the Solution class.
  • Static properties are shared among all instances of the class and can be accessed and modified from multiple threads concurrently.
  • Since there is no synchronization mechanism in place, concurrent access to the names array can lead to data races and inconsistent results.
  • If multiple threads attempt to modify the names array simultaneously, it can result in unexpected behaviour, such as incorrect or incomplete modifications, data corruption, or crashes.
  • To ensure thread safety, concurrent access to the names array should be synchronized using appropriate mechanisms like locks, serial queues, or other synchronization primitives.
  • Adding synchronization mechanisms will ensure that only one thread can access or modify the names array at a time, preventing data races and ensuring consistent behaviour.

Thread-safe solution

class ThreadSafeSolution {
    private static var names: [Int] = []
    private static let queue = DispatchQueue(label: "com.example.some-queue")

    static var countNames: Int {
        queue.sync {
            names.count
        }
    }

    static func addName(_ name: Int) {
        queue.async(flags: .barrier) {
            names.append(name)
        }
    }
}

Singleton

Extending our solution above to a real use case where we implement a SettingsManager, which manages a shared dictionary settings. The synchronization mechanism ensures that multiple threads can read the value from a setting key, but only one thread can modify the setting at one time.

class SettingsManager {
    static let shared = SettingsManager()
    private let serialQueue = DispatchQueue(label: "com.example.SettingsManager.serialQueue")
    private var settings: [String: Any] = [:]

    private init() {}

    func setValue(_ value: Any, forKey key: String) {
        serialQueue.async(flags: .barrier) {
            self.settings[key] = value
        }
    }

    func value(forKey key: String) -> Any? {
        var result: Any?
        serialQueue.sync {
            result = self.settings[key]
        }
        return result
    }
}

Actor

The recent introduction of structured concurrency to Swift has greatly simplify synchronised accesses to shared mutable data. You can use a new actor type to define shared mutable data types. I highly recommend you to read more about Sendable, Actor and Structured Concurrency

Quick Drop logo

Profile picture

Personal blog by An Tran. I'm focusing on creating useful apps.
#Swift #Kotlin #Mobile #MachineLearning #Minimalist


© An Tran - 2024