Concurrency in swift
In the previous section of this tutorial, we have discussed the GCD concepts in Swift, which allows Multithreading in swift. In this section of this tutorial, we will discuss the concurrent execution of the threads in swift. We will also include the types of Queues used by GCD and the QoS classes.
As we have already mentioned, the Grand-Central-Dispatch (GCD) uses the Dispatch queue, which is used for task submission where the tasks are executed on a first-in-first-out basis. In iOS, the process or application contains one or more threads; it is the operating system’s responsibility to schedule and manage the threads independently of each other.
However, each thread can be executed concurrently. The operating system decides which threads will execute concurrently, and when they will execute. One of the most used methods of archiving concurrency is Time Slicing, where each thread is given the same amount of time to be executed, and the system performs the context switch at every interval. The time-slicing is mostly archived in single-core systems.
On the other hand, the multi-core systems can use parallelism to execute multiple threads simultaneously. However, the GCD is built on the top of threads; it manages a shared thread pool where we can add blocks of code to dispatch queues. GCD always decides the amount of parallelism that is required based on the system and the available resources.
As we have already discussed in the previous section, the GCD operates on the dispatch queues. The dispatch queue in swift is an instance of DispatchQueue, where we submit the tasks to this queue. GCD executes the tasks in the dispatch queue in First in First Out order. Here, the dispatch queue is thread-safe, which can be accessed simultaneously by multiple threads.
However, the Queue can be concurrent or serial. As the name suggests, the serial queue executes only one thread at the given time. Here, then GCD decides the execution timing. We can never know the amount of time spent on the execution of a single task.
On the other hand, the concurrent queue executed multiple tasks at the same time. We can never know the amount of the time it takes to start the next tasks. The tasks will start executing in the same order they added. However, they may end in a different order. We cannot assume the number of threads running at a single time.
Here, it depends on GCD, when to start the thread. GCD also decides whether to run a task on a different core if the execution of two threads overlaps each other.
There are three types of a queue available for GCD.
- Main Queue: the main queue runs on the main thread, and it performs the serial execution of the thread.
- Global Queue: The Global queue is a concurrent queue and shared by the whole system. There are four global queues that operate on different priorities. The priorities are high, default, low, and background, where the background priority queue holds the minimum priority.
- Custom Queue: the developer creates the custom queues. They can be either concurrent or serial.
When the tasks are sent to global queues, we specify a quality of service class property. The QoS classes determine the priority of the tasks and then allow GCD to execute them.
There are the following categories of QoS classes present in the system.
- User Interactive: When we launch an application in iOS, to get a nice user experience, we need some tasks to be executed immediately. Such tasks are user interactive, which are to be executed for nice user experience. As a developer, we must use these tasks for UI Updates, event handling, and small workloads. The user-interactive tasks need to be executed on the main thread.
- User-Initiated: These tasks are initiated by the user from the user interface. These are asynchronous tasks that are to be used when the user waits in the application for immediate results, such as some API calls. The user-initiated tasks are executed in the high priority global queue.
- Utility: these are long-running tasks that run typically with a progress indicator. These types of threads are used for networking, computations, I/O, etc. These tasks are executed in the low priority global queue.
Background: these are the tasks that run in the application background. The user is not aware of these tasks. These tasks are used for prefetching, downloading, uploading, maintenance, and other similar tasks. This must be executed in the background global priority queue.