Liam SY Kim
by Liam SY Kim
4 min read

Categories

In Swift, Grand Central Dispatch API (GCD) sopports thread programming.

Just using GCD is not difficult, but there are many preceding concepts to understand.

After understanding concepts, I arrange three types of gcd queues, and queues examples accordingly.

Preceding concepts

Synchronous vs. Asynchronous

When the new thread is forked from original threa, we do the task parrallely.

Synchoronous origin thread wait until ending new thread. After new thread exit tasks, then origin thread get the return value of that thread, and continue the tasks.

Asynchoronous origin thread do not wait until the end of new thread. Therefore, Asynchoronous origin thread immediately get return value from new thread, and continue task.

Serial vs Concurrent Queue

iOS supports either serial queue and concurrent queue GCD.

ref : https://www.raywenderlich.com/5370-grand-central-dispatch-tutorial-for-swift-4-part-1-2

Serial queue is FIFO(First In, First Out), which usually called as queue in data structure concepts.

But then, what is concurrent queue?

ref : https://www.raywenderlich.com/5370-grand-central-dispatch-tutorial-for-swift-4-part-1-2

Before knowing concurrent queue, we need to know β€˜concurrent’ first.

It is easy to mistake that Concurrent is Parallelism.

When we do multi- threading, we can see threads are running parallely.

ref : https://www.raywenderlich.com/5370-grand-central-dispatch-tutorial-for-swift-4-part-1-2

System memory resource is limitied and should be occupied by a thread, OS needs to switch thread which occupying OS memory resource continously. we call this situation as Concurrency.

Therefore, Relationship between parallelism and concurrency is like below.

Parallelism requires concurrency, but concurrency does not guarantee parallelism.

These are all concepts which included in GCD.

Three types of gcd queues

Main queue

Main queue is queue running on the main thread of iOS, ans is serial queue.

Global queues

Global queues are running on the many thread in whole iOS, and they are all concurrent queues.

Especially, Global queue supports specific properties which is called Quality of Service (QoS). QoS has 4 properties which decides priority on concurrent global queue.

QoS

User - Interactive It is for UI task, and event handling which is short and must complete. Running on main thread, even global queue.

User-initiated It is for user request which requires immediate result whith ensuring non-block UI.

Utility Treat the task which takes long time. It usually used for calculating, networking, I/O.

Background The task which do not need for UI, and not that important as well.

and if you do not add any properties on glabal queue, this automatically set β€˜Default’ QoS property.

This example shows how to insert qos property on global queue.

// 1
DispatchQueue.global(qos: .userInitiated).async { [weak self] in
  guard let self = self else {
    return
  }
  let overlayImage = self.faceOverlayImageFrom(self.image)

  // 2
  DispatchQueue.main.async { [weak self] in
    // 3
    self?.fadeInNewImage(overlayImage)
  }
}


ref : https://www.raywenderlich.com/5370-grand-central-dispatch-tutorial-for-swift-4-part-1-2

Coustom queues

Custom queues are created by user, it can be either serial and concurrent.

Examples

Of course we read about the concepts about queues, but code examples can make us understand more easiler.

  • Sync vs Async
  • Serial vs Concurrent

Global Sync

this blog gave me insight to express example with fruit emoji.

  • https://zeddios.tistory.com/516

Global Sync prints pear, and the other just prints apple.


DispatchQueue.global().sync {
    print("global start!=============")
    for i in 1...5 {
       print("🍊"+" \(i)ea")
    }
    print("global end!  =============")
}

for i in 1...5 {
    print("🍎"+" \(i)ea")
}


Because Global queue synchronously excuted, the next task will be procceed after global queue task.

global start!=============
🍊 1ea
🍊 2ea
🍊 3ea
🍊 4ea
🍊 5ea
global end!  =============
🍎 1ea
🍎 2ea
🍎 3ea
🍎 4ea
🍎 5ea

Global Async

Global Async prints pear, and the other just prints apple.


DispatchQueue.global().async {
    print("global start!=============")
    for i in 1...5 {
       print("🍊"+" \(i)ea")
    }
    print("global end!  =============")
}

for i in 1...5 {
    print("🍎"+" \(i)ea")
}


Because Global queue asynchronously excuted, the next task excuted parallely.

// 1 trial
global start!=============
🍎 1ea
🍊 1ea
🍎 2ea
🍎 3ea
🍊 2ea
🍎 4ea
🍎 5ea
🍊 3ea
🍊 4ea
🍊 5ea
global end!  =============

// 2 trial
global start!=============
🍎 1ea
🍊 1ea
🍎 2ea
🍊 2ea
🍎 3ea
🍊 3ea
🍎 4ea
🍎 5ea
🍊 4ea
🍊 5ea
global end!  =============


Custom Serial Sync

Global Sync prints pear and peach, and the other just prints apple.

let WDFruits = DispatchQueue(label: "WD")

WDFruits.sync {
    print("custom start!=============")

    for i in 1...5 {
        print("πŸ‘"+" \(i)ea")

    }
    print("custom   end!=============")

}

WDFruits.sync {
    print("custom start!=============")

    for i in 1...5 {
        print("🍊"+" \(i)ea")

    }
    print("custom   end!=============")

}

for i in 1...5 {
    print("🍎"+" \(i)ea")
}

This example confused for me at first.

In summary,

Serial makes custom queue run first before running main task.

sync makes running peach first, rather than pear.

custom start!=============
πŸ‘ 1ea
πŸ‘ 2ea
πŸ‘ 3ea
πŸ‘ 4ea
πŸ‘ 5ea
custom   end!=============
custom start!=============
🍊 1ea
🍊 2ea
🍊 3ea
🍊 4ea
🍊 5ea
custom   end!=============
🍎 1ea
🍎 2ea
🍎 3ea
🍎 4ea
🍎 5ea

Custom Serial Async

Global Async prints pear and peach, and the other just prints apple.

let WDFruits = DispatchQueue(label: "WD")

WDFruits.async {
    print("custom start!=============")

    for i in 1...5 {
        print("πŸ‘"+" \(i)ea")

    }
    print("custom   end!=============")

}

WDFruits.async {
    print("custom start!=============")

    for i in 1...5 {
        print("🍊"+" \(i)ea")

    }
    print("custom   end!=============")

}

for i in 1...5 {
    print("🍎"+" \(i)ea")
}

Async makes do custom task parallely, and Serial makes serperate between custom queue and main task.

custom start!=============
πŸ‘ 1ea
🍎 1ea
🍎 2ea
πŸ‘ 2ea
🍎 3ea
πŸ‘ 3ea
🍎 4ea
🍎 5ea
πŸ‘ 4ea
πŸ‘ 5ea
custom   end!=============
custom start!=============
🍊 1ea
🍊 2ea
🍊 3ea
🍊 4ea
🍊 5ea
custom   end!=============

Conclusion

This is summary about GCD API. Futhermore, there are many other functions and properties in GCD. I will post more about it later.

I hope this summary and examples helps you:)