NEW: My new book Pro SwiftUI is out now – level up your SwiftUI skills today! >>

What is a synchronous function?

Paul Hudson    @twostraws   

Updated for Xcode 14.2

By default, all Swift functions are synchronous, but what does that mean?

A synchronous function is one that executes all its work in a simple, straight line on a single thread. Although the function itself can interact with other threads – it can request that work happens elsewhere, for example – the function itself always runs on a single thread.

This has a number of advantages, not least that synchronous functions are very easy to think about: when you call function A, it will carry on working until all its work is done, then return a value. If while working, function A calls function B, and perhaps functions C, D, and E as well, it doesn’t matter – they all will execute on the same thread, and run one by one until the work completes.

Internally this is handled as a function stack: whenever one function calls another, the system creates what’s called a stack frame to store all the data required for that new function – that’s things like its local variables, for example. That new stack frame gets pushed on top of the previous one, like a stack of Lego bricks, and if that function calls a third function then another stack frame is created and added above the others. Eventually the functions finish, and their stack frame is removed and destroyed in a process we call popping, and control goes back to whichever function the code was called from.

Synchronous functions have an important downside, which is that they are blocking. If function A calls function B and needs to know what its return value is, then function A must wait for function B to finish before it can continue. This sounds self-evident, I know, but blocking code is problematic because now you’ve blocked a whole thread – it might be sitting around for a second or more waiting for some data to return.

You’re probably thinking that waiting for a second is nothing at all, but in computing terms that’s an ice age! Keep in mind that the Neural Engine in Apple’s A14 Bionic CPU – just one part of the chip that powers the iPhone 12 – is capable of doing 11 trillion things per second, so if you block a thread for even a second that’s 11,000,000,000,000 things you could have done but didn’t.

One solution is to say “Well, if we’ve got a thread that’s currently blocked, we should just launch a new thread.” That’s definitely a solution, but it’s also a path towards thread explosion and we’ve already covered why that’s every bit as bad as it sounds.

So, although synchronous functions are easy to think about and work with, they aren’t very efficient for certain kinds of tasks. To make our code more flexible and more efficient, it’s possible to create asynchronous functions instead.

Hacking with Swift is sponsored by RevenueCat

SPONSORED In-app subscriptions are a pain to implement, hard to test, and full of edge cases. RevenueCat makes it straightforward and reliable so you can get back to building your app. Oh, and it's free if your app makes less than $10k/mo.

Learn more

Sponsor Hacking with Swift and reach the world's largest Swift community!

Similar solutions…

Buy Pro Swift Buy Pro SwiftUI Buy Swift Design Patterns Buy Testing Swift Buy Hacking with iOS Buy Swift Coding Challenges Buy Swift on Sundays Volume One Buy Server-Side Swift Buy Advanced iOS Volume One Buy Advanced iOS Volume Two Buy Advanced iOS Volume Three Buy Hacking with watchOS Buy Hacking with tvOS Buy Hacking with macOS Buy Dive Into SpriteKit Buy Swift in Sixty Seconds Buy Objective-C for Swift Developers Buy Beyond Code

Was this page useful? Let us know!

Average rating: 4.9/5

Unknown user

You are not logged in

Log in or create account

Link copied to your pasteboard.