MKC

From the travel issue of northern Thailand, where there are many tourists lack of accommodation. Specifically, transportation of tourists in the top northern part of Thailand with up to 8 hours of…

Smartphone

独家优惠奖金 100% 高达 1 BTC + 180 免费旋转




How to use GCD and survive to brag about it

Grand Central Dispatch is a library that handles concurrent execution on iOS and OS X. It simplifies multi-thread work, and prioritizes tasks to optimize the performance of your app.

It looks scary at first, but getting to know GCD will make you want to experience it yourself (and then brag about it, obviously).

GCD uses queues to perform tasks, therefore tasks in a dispatch queue are being handled in FIFO order. This means that tasks start in the order that they were added to the queue.

All dispatch queues that GCD provides are thread-safe, and therefore can be accessed from multiple threads without any worries.

GCD has 2 kinds of queues:

Serial queues - only one task is executed each time. We already know that tasks are performed in the order that they were added to the queue, this guarantees that code won’t be accessed concurrently from multiple tasks in the queue. (Sounds like a way to handle reader-writer problem)

Concurrent queues - multiple tasks can execute concurrently. You only know that they start in the order they were added, but you don’t know in which order they finish or how many tasks are executing at a given time.

Using GCD properly means choosing the right queue and function for the job, so lets take a look at the queues that GCD has to offer.

There are 5 dispatch queues used by the system. You can access those queues but keep in mind not to abuse them, your’e not the only one using them.

This queue is the only queue which is allowed to update the UI. If this queue gets blocked it also means that the UI is blocked, that the app is not responsive and that nothing gets updated. So don’t call the main queue synchronously from the main queue. It will cause the main queue to wait for itself forever, as shown in the code below that you should never write:

Take into consideration that any serial queue calling itself synchronously will block the queue.

How do you decide which priority to use? and what is qos?

QoS stands for Quality of Service. OS decides which code should run at any given time, but it also allows you to participate in that decision making. This is how: QoS is an Enum you can use to tell OS which code is more urgent. QoS cases are also called classes and they are:

In addition to the main queue and the global queues, GCD provides you the option to create your own custom queues, either serial queues or concurrent queues.

Only the first argument in this init method is necessary. If you don’t specify anything for one of the other arguments it will fall back to default. Let’s look at some interesting arguments of this method:

label: String. A unique label for your dispatch queue, reverse DNS is a common choice here.

qos: DispatchQoS. You already know what it means :). Think of the priority for this dispatch queue your’e creating. When this argument is not specified the priority will be default.

attributes: DispatchQueue.Attributes. Enum with 2 cases, concurrent which makes this queue a concurrent queue, and initiallyInactive which tells the system not to run this queue yet, you will need to start the execution yourself by running queue.activate(). By the way, to create an initiallyInactive concurrent queue you simply give this argument an array with both values: [.concurrent, .initiallyInactive]. When this argument is not specified the queue will be serial and activated.

Let’s do one more thing with dispatch queue, we will handle the read-write problem.

So you have an array with data. What happens when multiple threads read and write to it simultaneously? It’s not safe to let one thread read while another thread is modifying the data.

Here’s how our simple data component looks:

You can see that the read method doesn’t check if dataArray is not being modified when retrieving the array. Also the write method doesn’t make sure the array is not being read while it changes the array.

One solution is to use a serial queue:

This way you make sure that dataArray cannot be read and write to at the same time.

Another solution can use concurrent queue efficiency, by letting all tasks run concurrently but uses a barrier on the block of code of writing to dataArray. This way when a task of writing is inserted to the queue it will wait for all other tasks to finish before it runs. Tasks inserted after this one will wait for it to finish before they start, so when writing to dataArray no reading is executing.

To do this we will use DispatchWorkItemFlags argument with enumeration case .barrier when calling async() method.

This post introduces GCD and how it works. It shows how to get access to the main queue, the global queues, how to create your own queues (both serial and concurrent) and finally demonstrates a lock in GCD style. There are more functions and concepts in GCD not mentioned here. I hope I got you curious about GCD and you will keep exploring it.

Add a comment

Related posts:

Angela Merkel is no friend of a stable European Union

Recently I have come across a number of people whom are supportive of Corbyn in the UK whilst being sympathetic towards Angela Merkel. It is understandable where such sentiment comes from: it was a…

Why online marketing is never that complicated.

Your message is simply a bridge. A bridge that demonstrates where they are now. The other side of the bridge is where they want to be. Your message paints a picture to what the other side is like. ……

My Week With GoCubes

Welcome to a new content feature on The Next Level. In addition to the TNL Brand Tracker and deeper analysis of Brands in eSports, I’m going to do a week long experiment with a different product and…