bolizhou
bolizhou

Reputation: 1218

Why we need dispatch_sync() on another queue instead of using the current queue/thread in iOS GCD

I read that dispatch_sync() would block the current thread and won't return back to it until the task that one would like to do synchronously was finished on a serial queue that dispatch_sync() requires to work on.

So basically it would stop the current thread and perform the task it has.

If that, why bother having another queue for this kind of task, why cannot we just put the task on the current thread.

After all, doing the task would block the current thread anyway.

Since dispatch_sync() wouldn't open another thread, then why do we bother opening another queue to do the task rather than doing it on the current queue/thread?

Hope I describe my confusion here clearly.

I am here comparing using dispatch_sync() on another queue with using the current thread/queue directly, so what I would like to know is in what use case, using dispatch_sync() on another queue would be better than using only the current queue.

This should be relevant to thread-safe and synchronization issue.

Upvotes: 2

Views: 764

Answers (2)

Paulw11
Paulw11

Reputation: 114836

There could be many reasons why you would want to do this, but one common use case is to guard a critical section of code. Say you have multiple threads that want to update an array. Arrays aren't thread safe so this could lead to the array becoming corrupted.

By using a dispatch_sync on to a serial queue and updating the array inside the dispatched block you can ensure that only one thread updates the array at a time. You need a synchronous dispatch because you want the requesting thread to wait until the array has been updated before continuing.

For example, here is a simple queue class that uses a serial dispatch queue to ensure thread safety when the underlying array is updated:

class Queue<T> {

    private var theQueue = [T]()

    private var dispatchQ = dispatch_queue_create("queueQueue", DISPATCH_QUEUE_SERIAL);

    func enqueue(object:T) {
        dispatch_sync(self.dispatchQ) {
            self.theQueue.append(object)
        }
    }

    func dequeue() -> T? {
        return self.dequeue(true)
    }

    func peek() -> T? {
        return self.dequeue(false)
    }

    private func dequeue(remove: Bool) -> T? {
        var returnObject: T?
        dispatch_sync(self.dispatchQ) {
            if !self.theQueue.isEmpty {
                returnObject = self.theQueue.first
                if (remove) {
                    self.theQueue.removeFirst()
                }
            }
        }

        return returnObject
    }

    func isEmpty() -> Bool {
        return self.theQueue.isEmpty
    }
}

Upvotes: 2

Ruchira Randana
Ruchira Randana

Reputation: 4179

dispatch_sync() would basically block the current thread until all it's tasks are done-Correct!

Why we have other methods like dispatch_async() is because in certain situations, we need to execute some tasks with parallelism or at least "near parallelism". Suppose you need to download a substantial file over the network. If we're to do this on the main thread, then all the UI will freeze until the download finishes. This is because, the UI needs to be drawn continuously so that the user experience is maintained well! You wouldn't like to see a frozen UI whenever you click a download button. Do you?

In such cases, we can use dispatch_async() so that the network task (downloading the file) gets executed on a different thread. Now, unlike the above case, the processor would very quickly switch from downloading the file to updating the UI. Therefore, the app will remain responsive. In other words, you will be able to use the app with good user experience.

Hope you're clear on why we need queues other than the main queue!

Upvotes: 0

Related Questions