What are synchronous and asynchronous methods and how do you use them?

Sometimes we expect an answer or a result right away. And sometimes, it might take a while. And sometimes, what we thought would be quick turns out to take longer.

If I ask you what’s the current time, then I expect some kind of answer even if that answer is “I don’t know.” And if I ask you for a favor, then I usually expect that you’ll start soon but probably not right away. What if you’re in the middle of an important phone call and I ask you for the time? It might take a little longer, right? Or if the favor is small and you’re not doing anything at the moment, then you might be glad to help immediately.

The point is, we can’t be sure how long something will take in the real world and the same thing is true in programming. A method that runs right away is called synchronous. And a method that runs later is called asynchronous.

The asynchronous method doesn’t exactly run later. It’s actually composed of two parts. The first part is a normal synchronous method that you can call and expect an immediate answer. The difference is that the method will start a new thread to perform the requested action. What you get back right away isn’t the result you want but instead information that will let you get your desired outcome later.

This frees the calling code to be able to do other tasks and periodically wait for the asynchronous task to complete. Listen to the full episode about these methods or you can read the full transcript below.

Transcript

Sometimes we expect an answer or a result right away. And sometimes, it might take a while. And sometimes, what we thought would be quick turns out to take longer.

If I ask you what’s the current time, then I expect some kind of answer even if that answer is “I don’t know.” And if I ask you for a favor, then I usually expect that you’ll start soon but probably not right away. What if you’re in the middle of an important phone call and I ask you for the time? It might take a little longer, right? Or if the favor is small and you’re not doing anything at the moment, then you might be glad to help immediately.

The point is, we can’t be sure how long something will take in the real world and the same thing is true in programming. A method that runs right away is called synchronous. And a method that runs later is called asynchronous.

We normally have an idea if something can be done right away or not. And it helps to plan one way or another. Calling a method is the same. Or at least it should be. Here’s what I mean.

Most methods that you call will be very clear if they run right away or not. This is because when a method can run later, then there needs to be some way for the asynchronous method to communicate back to you when it’s done. Sure, it’s possible to design a system where method calls all look synchronous and there’s some roundabout way to find out when they complete and get the results but I wouldn’t want to use a system like that. It’s just too confusing.

Let’s take a simple method called removeCakeFromOven that returns void and takes no parameters. If I had code that called such a method, then I’d expect the method to begin running right away and complete fairly soon in a synchronous manner. In fact, the normal method calling protocol causes my code to stop running and the processor goes right into the removeCakeFromOven code. When the removeCakeFromOven code eventually hits a return statement, then it’s done and the processor switches back to the next line in my code right after I called the removeCakeFromOven method. In other words, my code continues running right where it left off. There’s a builtin ability to synchronize the call of this type of method with it’s return. That’s why normal methods like this are call synchronous.

And it’s important to realize that all of this is done in the same thread. Just calling a method doesn’t switch threads.

However, calling a method that’s designed to run asynchronously will look very different. This is because there’s two parts to an asynchronous method. The first part is actually just a normal synchronous method that has some extra parameters or maybe it uses a special return type to allow you to know when it completes and when your result is ready. If some code calls an asynchronous method, then the same blocking happens. The processor will stop running the code in the calling method and switch into the asynchronous method. And again, all this will be done in the same thread. You can’t just switch threads by calling a method.

What changes is the behavior of the asynchronous method. Instead of taking the time to complete the operation right away, it creates a new thread. Or maybe it uses a thread that’s already waiting. One way or another though, it needs to bring in another thread that will actually do the work. The thread is given all the information it needs and then left to run in its own time. Once this is done, then the asynchronous method returns with some information about the thread it just launched. The calling code can use that information to later get the results.

So even an asynchronous method is really just a synchronous method that begins another thread and returns right away. It’s called asynchronous because it’s the result that the calling thread is looking for and that result can come back in it’s own time.

I’ll explain how asynchronous methods return right after this message from our sponsor.

( Message from Sponsor )

If you remember nothing else from this episode, just remember that method calls are always run by the thread making the call. This could be a normal method, a class method, a pointer to a method or a delegate, a functor which is a class that overrides the method call operator, a lambda or a closure. Whenever you actually make a method call, it will be done on the current thread.

This is one situation where real life can sometimes be very similar to computers and also be quite different. Let’s say that you represent a thread and your friend is another thread. This is a good analogy because you can be doing things and your friend can be doing different things all at the same time.

Now, you ask your friend to bring you lunch. In a way, this is like calling an asynchronous method. You take the time to communicate the desire for lunch and then continue about your other business. Sometime later, your friend comes back and hands you your lunch. This is the part where programming is different from real life. In real life, you and your friend can interact directly. In programming, threads don’t have this level of interaction.

The way the lunch would be returned in programming terms means that your friend would come back, place your lunch in some predetermined location and then signal an event. Your friend would then go back to some other task.

You wouldn’t be able to see your friend walk up to you. Threads can’t see each other like that. You might be able to keep checking the predetermined location to see if the lunch sort of magically appears. This is called polling and is not very efficient. Just imagine yourself continually walking to the refrigerator and seeing the empty location, going back to your work, and getting up again to check the refrigerator. You’ll get tired of this real quick and so does the computer.

A much better way would be for you to wait for the signal. You could even wait for a specified amount of time and if the signal still hasn’t arrived, then go do some work for a while and then wait for the signal again. Waiting for the signal is like going to sleep for a while. This is much better.

I’ll continue a similar topic in the next episode. For now though, you should also realize that the task running in the other thread asynchronously needs its own locks. If you’re holding the lock to the refrigerator the whole time that you’re waiting for your lunch, then you’re going to go hungry. Because the other thread, your friend in this example, will wait for the lock before placing the lunch in the refrigerator. Your friend can be standing right next to the refrigerator trying to put your lunch inside but unable to make any progress because you have the door open. The lunch never appears and the signal never gets sent.