2

I have some idea about JS and was going through iOS

I was reading this blog and am confused about async and sync in Swift (although I have a feeling that it's same in IOS and Javascript) but anyway

import UIKit 

func smile () {
    print('1')
}

func love() {
    print('2')
}

//Serial Queue

let queue = DispatchQueue(label: 'SerialQueue')

queue.async {
    for _ in 1...5 {
     smile()
  }
}

 queue.async {
    for _ in 1...5 {
     love()
   }
 }

This would log something like this 1

1
1
1
1
2
2
2
2
2

Thinking about the example, If it was a sync instead of async then the output would've been the same? so what's the use of using async above?

Also, In JS we need to await. In swift we don't have to do anything? Can someone explain it to me by giving example of async and await in swift?

1
  • I think you would benefit from diving more into async/await (as seen in javascript, but also other languages), and understand precisely what it does. Commented Feb 3, 2020 at 14:31

3 Answers 3

2

Since you're using the same queue for both works, the second async block won't start executing until the first block ends. It doesn't matter if it's asynchronous or serial.

You'll see the true difference between .async and .sync if you add a print statement between both queues. Like this:

queue.async {
    for _ in 1...100 {
          self.smile()
    }
}
print("Finished printing smiles")
queue.async {
    for _ in 1...100 {
          self.love()
    }
}

The previous code will probably print "Finished printing smiles" even before it has started printing smiles! That's because async work returns instantly and keeps executing code.


And let's see what happens if you change the queues with synchronous queues:

queue.sync {
    for _ in 1...100 {
          self.smile()
    }
}
print("Finished printing smiles")
queue.sync {
    for _ in 1...100 {
          self.love()
    }
}

Yup. Now the sync queue waits before the closure completes before carrying on. So, you'll get 100 smiles, and then the "Finished printing smiles".


If you want to achieve concurrency, that's it, two blocks of code executing simultaneously (but not at exactly the same time, because that would be parallelism), you'll have to use two different queues, or specify the .concurrent parameter in the queue configuration:

override func viewDidLoad() {

    let queue = DispatchQueue(label: "SerialQueue")
    let queue2 = DispatchQueue(label: "AnotherQueue")

    queue.async {
        for _ in 1...100 {
              self.smile()
        }
    }
    print("Finished printing smiles")
    queue2.async {
        for _ in 1...100 {
              self.love()
        }
    }
}

As you'll see, the order here is chaotic and will vary between executions. That's because both queues are running at the same time.

Another equivalent to this code would be:

let queue = DispatchQueue(label: "ConcurrentQueue", attributes: .concurrent)

queue.async {
    for _ in 1...100 {
          self.smile()
    }
}
print("Finished printing smiles")
queue.async {
    for _ in 1...100 {
          self.love()
    }
}
Sign up to request clarification or add additional context in comments.

Comments

2

@loufranco and @Roberto has answered in detailed way.

You can also achieve this on a single OperationQueue adding different BlockOperation on it.

As if you will see in this scenario:

let queue = OperationQueue()

let operation1 = BlockOperation {
    for _ in 1...5 {
     smile()
  }
}
print("Done")
let operation2 = BlockOperation {
    for _ in 1...5 {
     love()
   }
 }

queue.addOperation (operation1)
queue.addOperation (operation2)

The output is :

enter image description here

And if you will add operation2 dependency on operation1:

operation2.addDependency(operation1)
queue.addOperation (operation1)
queue.addOperation (operation1)

The Output is :

enter image description here

Comments

0

When you use sync, it executes in the queue’s thread, but sync doesn’t return until it is done. async returns immediately.

Because you have a serial queue, the prints are the same, but the calling function can return before the queue has done the printing. If it were sync, the calling function would be waiting for the prints to finish.

There is no async/await concept in Swift yet. That is not what is happening here (or in the sync case)

If you want to see the difference, put sleeps in the blocks and prints outside the queue calls.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.