ProgrammingMobile Developer

Explain the essence of GCD (Grand Central Dispatch) and DispatchQueue in Swift, how to properly create asynchronous code, and what pitfalls can arise when working with multithreading?

Pass interviews with Hintsage AI assistant

Answer.

Background

Grand Central Dispatch (GCD) was introduced to iOS and macOS in 2009 as a low-level system for organizing concurrent, asynchronous code (multithreading), based on queues — DispatchQueue. GCD proved to be much more concise than manual thread management, providing safe task execution, synchronization, and a convenient API.

Problem

Asynchronicity and multithreading are traditionally a source of most issues: data races, deadlocks, UI freezes, and complicated crashes. Incorrect use of queues or attempts to access the UI from a non-main thread lead to bugs.

Solution

Swift makes it easy to create background work and safely return to the main thread to update the interface using global and custom queues. Use DispatchQueue for asynchronous work and DispatchGroup if you need to wait for a set of asynchronous tasks to complete.

Code example:

let backgroundQueue = DispatchQueue(label: "background", qos: .background) backgroundQueue.async { // executed in the background thread let image = downloadImage() DispatchQueue.main.async { // safe UI update imageView.image = image } }

Key features:

  • DispatchQueue.async executes a block asynchronously
  • DispatchQueue.main.async for calls on the main thread
  • DispatchSemaphore, DispatchGroup, sync, and qos for controlling task priority

Tricky questions.

What happens if you call sync on the main queue from the main thread?

A deadlock occurs: the main thread waits for a task to run on itself, and the application “freezes.”

DispatchQueue.main.sync { // DEADLOCK }

Can a DispatchQueue.serial execute tasks in parallel?

No, a serial queue always executes tasks one by one; however, if multiple serial queues are created, they can run in parallel with each other.

Is it allowed to update the UI from a non-main thread?

No, any manipulations with UIKit (or SwiftUI View rendering) can only be done from DispatchQueue.main. Violating this will lead to unstable operations and crashes.

Common mistakes and anti-patterns

  • Synchronous calls on the main thread (deadlock)
  • Attempting to update the UI from the background
  • Uncontrolled resource race when writing to shared variables
  • Using global queues unnecessarily, lack of dedicated queues

Real-life example

Negative case

Data is loaded in the background thread; the UI is updated immediately — the application sometimes crashes or the interface hangs. Additionally, shared mutable state is used between threads without synchronization.

Pros:

  • The code is visually concise

Cons:

  • Unstable bugs and rarely reproducible crashes
  • Performance losses

Positive case

Organizing all UI updates only on DispatchQueue.main, dedicated queues for working with large data, using DispatchGroup to manage the completion of asynchronous tasks.

Pros:

  • No races
  • Effective workload division across threads
  • Easy to maintain

Cons:

  • Many "context switches" between threads, discipline required when working with shared resources