Home > Enterprise >  Swift: DispatchQueue always Serial?
Swift: DispatchQueue always Serial?

Time:11-26

I receive a lot of data and want to process it off the main thread. Most of the things can be asynchronous in nature, however sometimes there is critical data coming in with each update invalidating the previous iteration. At the moment I set up everything like this:

func onReceivedData(d: Data){ //is on main thread unfortunately
    //some work 1
    DispatchQueue.global(qos: DispatchQoS.QoSClass.userInitiated).async {
        //some work 2
        if(saveToFile) {
            DispatchQueue.global(qos: DispatchQoS.QoSClass.utility).async {
                //UserDefaults write
            }
        }

    }
}

Now I am not sure if I understood the DispatchQueue correctly. Is it possible when data A comes in before data B, that data B for some reason may reach the UserDefaults write earlier than data A? Do the DispatchQueues push operations in a serial manner or can they also operate in parallel, potentially writing data B before data A, leaving the UserDefaults in an invalid state?

CodePudding user response:

From the Apple Developer documentation on DispatchQueue.global():

Tasks submitted to the returned queue are scheduled concurrently with respect to one another.

This means that the global() queues are concurrent dispatch queues. If you want to ensure that the tasks execute in the order that you schedule them, you should create your own serial DispatchQueue.

let queue = DispatchQueue(label: "my-queue")
queue.async {
    // Work 1...
}
queue.async {
    // Work 2...
}

"Work 1" will always run before "Work 2" in this serial queue (which may not be the case with a concurrent queue).

Alternatively, you could look into using a Swift actor which can more efficiently control access to shared mutable state in a memory-safe way.

  • Related