swift - Grand Central Dispatches - execution out of order? -


i'm trying better understanding of gcd wrote test code below (bottom). 2 functions waits inside sent on different queues , println on main thread waiting particular tasks.

i expect console output should be:

before functions start 3 sec loop start 5 sec loop end 3 sec loop between functions wait on long after functions wait on long end 5 sec loop between functions wait on longer after functions wait on longer 

but instead is:

before functions start 3 sec loop start 5 sec loop between functions wait on longer after functions wait on longer end 3 sec loop between functions wait on long after functions wait on long end 5 sec loop 

a number of things don't make sense me - 1. why "longer" ones printed before "long"? 2. why "longer" ones not printed after end of longer i.e. 5 second function?

code (viewcontroller.swift)

import uikit  class viewcontroller: uiviewcontroller {    var longqueue = dispatch_group_create()   var longerqueue = dispatch_group_create()   var queuelow = dispatch_get_global_queue(dispatch_queue_priority_low, 0)   var queuehigh = dispatch_get_global_queue(dispatch_queue_priority_high, 0)    override func didreceivememorywarning() {     super.didreceivememorywarning()   }    override func viewdidload() {     super.viewdidload()      println("before functions")      dispatch_async(queuehigh) {       self.longfunc()     }      dispatch_group_notify(longqueue, dispatch_get_main_queue()) {       println("between functions wait on long")     }     dispatch_group_notify(longerqueue, dispatch_get_main_queue()) {       println("between functions wait on longer")     }      dispatch_async(queuelow) {       self.longerfunc()     }      dispatch_group_notify(longqueue, dispatch_get_main_queue()) {       println("after functions wait on long")     }     dispatch_group_notify(longerqueue, dispatch_get_main_queue()) {       println("after functions wait on longer")     }   }    func longfunc () {     dispatch_group_enter(self.longqueue)       println("start 3 sec loop")       sleep(3)       println("end 3 sec loop")     dispatch_group_leave(self.longqueue)   }    func longerfunc() {     dispatch_group_enter(self.longerqueue)       println("start 5 sec loop")       sleep(5)       println("end 5 sec loop")     dispatch_group_leave(self.longerqueue)   }  } 

there 2 categories of problems here:

  1. you entering dispatch groups inside longfunc , longerfunc. but, because you're dispatching calls functions respective queues, have no assurances you're going reach dispatch_group_enter before reach dispatch_group_notify calls perform in viewdidload on main thread. remember code dispatched background queues runs asynchronously , have no assurances when runs versus code continuing execute on main thread. key if encounters dispatch_group_notify before you've entered group, notify closure fire immediately.

    to avoid race condition, either want perform dispatch_group_enter in viewdidload before dispatch code background queues (and obviously, before set notify closure), or want retire entering , leaving of groups , replace dispatch_async dispatch_group_async. either of approaches ensure enter groups before add notify closures groups.

  2. the dispatch notify closure reports "between functions wait on longer" more egregious example, there's not race condition. adding notify closure before dispatch function later enter group. fire before code dispatched queue.


Popular posts from this blog