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()
}
}