The purpose of having a synchronising thread

Viewed 118

The following piece of code supposedly sets up a thread-safe singleton:

class Singleton {
    static var shared = Singleton()
    private let internalQueue = DispatchQueue(label: "SingletionInternalQueue", qos: .default, attributes: .concurrent)

    private var _foo: String = "aaa"

    var foo: String {
        get {
            return internalQueue.sync { _foo }
        }
        set (newState) {
            internalQueue.async(flags: .barrier) { self._foo = newState }
        }
    }

    func setup(string: String) {
        foo = string
    }
}

Source: Thread safe singleton in swift

But I don't understand the purpose of this.

For example, if I wish to get the value of foo, shouldn't I be able to just read it? The operation should always be performed on the main thread, so what is the point of adding another thread?

Similarly with set: if I am worried about multiple sources setting the value at the same time, can't we simplify that code and eliminate the .barrier parameter?

internalQueue.async(flags: .barrier) { self._foo = newState}

If it is in a sync block, doesn't this force it onto the main thread? If so, then why wouldn't the code only need to be self._foo = newState?

1 Answers

You are correct: As long as you only access the singleton from the main thread, there is no need for synchronization. In that case, I'd prefer to make that an explicit requirement by using code like this:

assert(Thread.isMainThread)

This will be optimized away in production builds, but will make sure you pick up inadvertent programming errors in debug mode (e.g. when you call your code from a URLSession completion handler).

Related