What's the difference between synchronous and asynchronous calls in Objective-C, versus multi-threading?
Asked Answered
P

7

59

For the longest time I thought asynchronous was synonymous to running something on a background thread, while synchronous meant on the main thread (blocking UI updates and interactions). I understand that not running on the main thread for expensive actions is because it doesn't allow UI actions to occur as the main thread is occupied, but why is synchronous troublesome?

However, it's since came to my attention that you can make asynchronous calls on the main thread, and synchronous calls on background threads.

I always hear people saying not to use expensive calls synchronously or on the main thread, as it will block the UI for the user. Are these two separate issues I should be making sure I don't do? What are the differences?

Precognition answered 14/1, 2014 at 20:1 Comment(0)
I
110

When you invoke something synchronously, it means that the thread that initiated that operation will wait for the task to finish before continuing. Asynchronous means that it will not wait.

Having said that, when people suggest that you perform some slow or expensive process asynchronously, they are implicitly suggesting not only that you should run it asynchronously, but that you should do that on a background thread. The goal is to free the main thread so that it can continue to respond to the user interface (rather than freezing), so you are dispatching tasks to a background thread asynchronously.

So, there are two parts to that. First, using GCD as an example, you grab a background queue (either grab one of the global background queues, or create your own):

// one of the global concurrent background queues

dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

// or you could create your own serial background queue:
//
// dispatch_queue_t queue = dispatch_queue_create("com.domain.app.queuename", 0);

Second, you dispatch your tasks to that queue asynchronously:

dispatch_async(queue, ^{
    // the slow stuff to be done in the background
});

The pattern for operation queues is very similar. Create an operation queue and add operations to that queue.

In reality, the synchronous vs asynchronous distinction is completely different from the main queue vs background queue distinction. But when people talk about "run some slow process asynchronously", they're really saying "run some slow process asynchronously on a background queue."

Induline answered 14/1, 2014 at 20:26 Comment(1)
A good way to understand this with Swift is that the ".sync" or ".async" part means "from where we are now". So, regardless of where you send it, .sync, wait for it ("where we are now") or .async, don't wait for it ("where we are now").Shaeffer
B
33

"Synchronous" essentially means "in order." Basically, when you do a synchronous operation, everything that comes later has to wait for the operation to finish before they can start.

Conversely, "asynchronous" more or less means "not in order." When you do something asynchronously, the following code can immediately run and the asynchronous operation will be run…sometime. It might be run in parallel with the rest of the code on another thread. It might simply be scheduled for some other time on the same thread.

The concept of synchronicity doesn't have anything to do with particular threads, per se. It's just about whether you have to wait for an operation to finish or not.

Where the main thread comes into this in a big way is in Cocoa (Touch) programs. The AppKit runs the main event loop on the main thread, so if the main thread is waiting for an operation to complete, it can't process any input or update the UI. If you have a piece of code running on a background thread, though, running synchronous code will not block the main event loop, because it isn't the main thread that's waiting for the synchronous operation to complete.

Similarly, a long-running asynchronous operation from a background thread that you place on the main thread can cause problems, because while the background thread isn't going to wait for the operation to complete, it is still taking up time on the main thread where the event loop needs to run.

Balanchine answered 14/1, 2014 at 20:14 Comment(0)
S
18

Lets us take some easy examples :

Asynchronous call with multithreading :

// Methods gets called in different thread and does not block the current thread. 
[NSURLConnection sendAsynchronousRequest:request 
                                   queue:queue 
                       completionHandler:
    ^(NSURLResponse *response, NSData *data, NSError *error) {
}];

Synchronous call with multithreading:

//Do something
dispatch_sync(queue, ^{
    //Do something else
});
//Do More Stuff

Here you got //Do something //Do something else and //Do More stuff done consecutively even though //Do something else is done on a different thread.

Usually, when people use different thread, the whole purpose is so that something can get executed without waiting. Say you want to download large amount of data but you want to keep the UI smooth.

Hence, dispatch_sync is rarely used. But it's there. I personally never used that. Why not ask for some sample code or project that does use dispatch_sync.

Asynchronous call with one thread :

[self performSelector:@selector(doSomething) withObject:nil afterDelay:0];

Here current runloop to complete before 'doSomething' is called. In other words, the current call stack can be completed (the current method returns) before 'doSomething' is called.

Synchronous call with one thread:

 [self doSomething];

I don't think you need explanation for this.

In general asynchronous activity is not same as threading , however in iOS they are implemented using the this fashion. Its not true for all languages. We usually manage different asynchronous task using run loops.

Suspensor answered 14/1, 2014 at 20:29 Comment(0)
P
9

swift 3, 4, 4,2 Synchronous means that thread that initiated that operation will wait for the task to finish before continuing.

DispatchQueue.main.sync {

}

Asynchronous means that Completes a task in background and can notify you when complete means it will not wait.

DispatchQueue.main.async {

}
Platen answered 16/7, 2018 at 6:26 Comment(0)
C
3

Asynchronous means out of line, synchronous means in line. You can perform synchronous tasks and block multiple threads at once.

If you are in a background thread and want to update a whole bunch of the user interface you call out to the main thread in a dispatch queue. If you call dispatch_sync then the code you are currently in waits for the dispatch to complete, thereby blocking the background thread you are in and blocking the UI while it updates the main thread.

But if you called dispatch_async the background thread would continue with the rest of the code listed and the main thread would run the requested dispatch block.

The same can be said when in the main thread. if you call a dispatch_sync from the main thread into a global or custom queue it will block the main thread while it runs the code in a separate thread. I can't say I know of a case where that would be used, but it's surely possible.

Whenever you have calculation code, webservice code, fetching code, whatnot that does not affect the UI it is best to do it in a separate thread. For this kind of stuff I would do a dispatch_async into a global thread. Then when that code is completed I would run a dispatch_async back into the main thread to tell it to update the UI with whatever I just calculated.

Synchronous means blocking, asynchronous means it will complete at a later time (maybe right now) without blocking what you are currently doing.

Committeeman answered 14/1, 2014 at 20:12 Comment(0)
G
2

This discussion pretty much answers it: Asynchronous vs Multithreading - Is there a difference?

In the general case, an asynchronous call does not necessarily create a new thread. That's one way to implement it, with a pre-existing thread pool or external process being other ways. It depends heavily on language, object model (if any), and run time environment.

Asynchronous just means the calling thread doesn't sit and wait for the response, nor does the asynchronous activity happen in the calling thread.

So basically, other activities can happen while waiting for something to load, but it may or may not be done on separate threads.

Gyro answered 14/1, 2014 at 20:11 Comment(0)
D
1

Sync vs Async

Sync and async operations are about execution order a next task in relation to the current task.

Let's take a look at example where we have three tasks(Task 1, Task 2, Task 3) and we will operate by Task 2. Task is an atomic operation - method call in a stack (method frame).

Synchronous

Implies that tasks will be executed one by one. A next task is started only after current task is finished. Task 3 is not started until Task 2 is finished.

Sync + Single Thread = Sequential

DispatchQueue.main.sync causes deadlock if you call it from the main thread

main() {
    task1()
    task2()
    task3()
}

Sync + Multi Thread = Parallel

Blocked means that a thread is just waiting(although it could do something useful. e.g. Java ExecutorService[About] and Future[About])

DispatchQueue.global().sync()

main() {
    task1()
    Future future = ExecutorService.submit(task2())
    future.get() //<- blocked operation
    task3()
}

Asynchronous

Implies that task returns control immediately with a promise to execute a code and notify about result later(e.g. callback, feature). Task 3 is executed even if Task 2 is not finished. async callback, completion handler[About]

Async + Single Thread = Concurrent

Callback Queue (Message Queue) and Event Loop(RunLoop, Looper)[About] are used. Event Loop checks if Thread Stack is empty and if it is true it pushes first item from the Callback Queue into Thread Stack and repeats these steps again. Simple examples are button click, post event...

Timer.scheduledTimer(withTimeInterval: 2, repeats: false)

main() {
    task1()
    ThreadMain.handler.post(task2());
    task3()
}

Async + Multi Thread = Concurrent and Parallel

For example when you need to make some calculations on another thread without blocking. You are able use result of Task 2 using a blocking method get() or using async callback through a loop.

DispatchQueue.global().async()

main() {
    task1()

    new Thread(task2()).start();
    //or
    Future future = ExecutorService.submit(task2())

    task3()
}

Examples

For example in Mobile world where we have UI/main thread and we need to download something we have several options:

  • sync block - block UI thread and wait when downloading is done. UI is not responsive.
  • async callback - create a new tread with a async callback to update UI(is not possible to access UI from non UI thread). Callback hell.
  • async coroutine[About] - async task with sync syntax. It allows mix downloading task (suspend function) with UI task.

[Concurrency vs Parallelism]
[iOS GCD]

Duration answered 24/1, 2023 at 18:15 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.