iOS Concurrency with GCD and Operations - Part 2: | Ray Wenderlich

Learn the basics of concurrency and Grand Central Dispatch — serial and concurrent queues, synchronous and asynchronous dispatch.


This is a companion discussion topic for the original entry at https://www.raywenderlich.com/3648-ios-concurrency-with-gcd-and-operations/lessons/2

Links mentioned in this video:

I am trying to run the playground provided (Terminology) (both the starter that I have edited and the finished one provided) and when I do that, I get no output and the playground continues to run and does not stop.
I must be missing something. Can you help?

I’m using Xcode 8.1. I downloaded what you would’ve gotten and it runs ok.

Try quitting Xcode and restarting. If that doesn’t work, try restarting your Mac?

oh yes, I’m on Sierra

Thanks for your very quick response. I was using xCode 8.2 beta but when I switched to 8.1 it works fine. Now, it could be that I have a messed up install with multiple versions of xCode so others may not experience the same issue with 8.2 beta
I noticed that when I ran it in 8.1 it first indicated that it was launching the simulator so I could have broken that piece in my 8.2 install.
Thanks again for the quick response.

Xcode 8 betas seem to be doing strange things, even if they’re not open. Some of us were complaining in a slack channel that the command-/ to comment had stopped working in the released Xcode 8. Then one guy discovered that deleting the beta from his Mac fixed the problem — he wasn’t using it, it was just sitting there, unopened! Sure enough, I deleted my beta copy and I could comment lines again!

There is an error in the ChallangeFinished code…
The asyncTiltShift function runs the completion handler on the runQueue and never uses completionQueue…

good catch! I should’ve set resultQueue to the default queue, run completion(outputImage) in resultQueue, and noted again that the main queue behaves strangely in playgrounds.

I’ll see if we can replace the ChallengeFinished soon.

edited to add: I actually set resultQueue correctly in the challenge starter, but forgot to update the finished playground :flushed:

1 Like

:thumbsup: Great series so far. Looking forward to the rest!

@audrey You have mentioned in this video that iPhone and iPads before 2011 were having single processors. So on those phones Serial and Concurrent queues will be same in terms of functionality? My reasoning behind it is, there only context switching will happen as more than one thread can’t run simultaneously. So if it is true, then priority given to main thread will be far far more than in phones having multicore as UI should have minimal impact of single Core.If i am using Concurrent queue and my app is running on single core phone, then would it have a negative impact? Also can context switching happen between tasks in serial queue or they will be always excecuted in FIFO order from Start to completion?

hi Keshav: yes, concurrency on a single CPU is achieved by multiplexing / context switching. User interaction doesn’t actually require much CPU attention: people are pretty slow compared with a CPU. I found this account by Oleg Andreev, who did a little experiment with a single-CPU iPhone 4: Oleg Andreev - Fun with concurrency on a single core.

[When] the app was rendering graphics on the main thread. 90% of CPU time was spent on graphics, 10% on gesture recognition and related computations. Overall CPU utilization was about 30%… [after moving OpenGL rendering to serial dispatch queue] the rendering was indeed slightly smoother, but touches were still delayed… 70% of CPU time was spent on graphics (in background thread) and 30% was spent on gesture recognition. Also, overall CPU usage increased up to 50%.

Tasks in a serial queue run FIFO in the sense of first-ready-first-run.

1 Like

Hi Audrey,
I understand making use of sync to avoid race condition. But is it necessary to use a serial queue ?
Can we do the same thing on a concurrent queue and avoid race condition ?

hi Preetham: in part 11, we use a dispatch barrier with a concurrent queue to make a variable thread safe.

1 Like

okay. Thanks a lot for the quick response. Right now in part 2… Will get back if I have any queries . Thanks a lot

I have doubt about how sync removes race condition, in the example:

value = 42
mySerialQueue.sync {
  changeValue()
}
value

As you explained earlier in the video, sync actually runs the code in the current thread, isn’t it simpler just call it directly? Like this:

value = 42
changeValue()
value

Thanks for you further explanation.

hi Daiwen: sync blocks the current thread while the task runs on mySerialQueue. So, in this example, the value statement doesn’t run until changeValue() has finished.

In the async version, the value statement runs immediately, so shows the old value.

hi Audrey, thank for your tutorial.
I can not find different sync - serial and sync - concurrent.
I see it works the same.

there’s a nice example at ios - DispatchQueue Sync Concurrent - Stack Overflow

when you dispatch sync to a concurrent queue from two loops, the results can appear in a different order on each run, because the concurrent queue can run more than one task at a time, and you get a race condition

when you dispatch sync to a serial queue from the two loops, the results appear in alternate order each time, because the tasks run in exactly the same order they get added to the serial queue

the usleep(100) seems to favour the second loop: the runner1 result always appears first; if I comment out the sleeps, the runner0 result appears first.

2 Likes

Hi Audrey, great tutorial! Very clear and concise. I finished the whole course and reorganized my own knowledge and code ever used at work.

My other previous co-workers ever used DispatchSemaphore, is it old Objective-C thread safe tools, or part of GCD? Can I use serial queue to replace semaphore in the project? Thanks!

hi Mike! DispatchSemaphore is part of GCD, and is still useful.

Soroush Khanlou’s GCD Handbook shows a couple of uses.

However, Rob’s stack overflow answer advises against over-use of dispatch semaphores:

while the dispatch semaphore technique is a wonderful technique when absolutely needed, I must confess that I see too many new developers, unfamiliar with good asynchronous programming patterns, gravitate too quickly to semaphores as a general mechanism for making asynchronous routines behave synchronously.

And WWDC 2015 and 2016 GCD talks have pointed out that Apple’s priority inversion fix (promoting lower priority tasks) doesn’t work with dispatch semaphores, because they don’t have an owning task, so the system can’t tell where they’re being triggered.

Earlier in the WWDC 2015 talk, they discuss the use of serial queues as locks. Serial queues can take advantage of the priority inversion fix, so if that’s a factor in your project, you should try to use a serial queue. OTOH if it’s not broken … ;]

1 Like