Dispatch Groups

Dispatch group demo xCode 8.3.3

DispatchQueue uses enter() and leave() to group chunks of code into one work item and process them in the group. This can be done async or sync.

Note that DispatchQueues do not use sync, because the purpose would not make sense. The whole purpose of a DispatchGroup is to have multiple tasks run, and notify when they are done. Since sync is done one by one, and in order, there is no purpose to notify anything due to the nature of sync: Each task must begin and end in order.

Source Code

First, take note that we are looping through placing code chunks onto a global queue via async operation. Thus,

Then these 4 code chunks gets processed by the global queue asynchronously. Their initial lines gets printed:

—– code execution entered dispatchGroup for index 0 ——
—– code execution entered dispatchGroup for index 2 ——
—– code execution entered dispatchGroup for index 3 ——
—– code execution entered dispatchGroup for index 1 ——
code execution 0 start
code execution 2 start
code execution 3 start
code execution 1 start

This means that for each code chunk, that code chunk has placed a section of code into the dispatchGroup. In our case, the section of code prints 0 to 100.
The dispatchGroup now has 4 section of code to process.

The dispatchGroup will now execute the 4 section of code asynchronously.

Due to code chunk 0’s NO SLEEP, it simply does its printing first and it does it fast. Code chunk 1 can’t start because it requires every loop to sleep for 0.01 seconds before it starts. Thus, since code chunk 0’s loop does 0 sleep, it prints all first.

Then code chunk 1 starts, and sleeps for 0.01 between each print. Code chunk 2 will also start, and it sleeps for 0.02 between each print….

Due to

index 1’s loop having to sleep 0.01ms,
index 2’s loop having to sleep 0.02ms,
index 3’s loop having to sleep 0.03ms,

for every iteration, you can see that index 1’s printing of its loop is just a tad bit faster than index 2 and index 3’s loops.

index 1’s code chunk finishes and thus, it leaves the group.

eventually index 2’s code also finishes and leaves the group. Then index 3 will finally group after printing its loop.

Then when the group is finally empty, it will notify us and process the code block to print “Block 4”. Since this command is within the for loop, it will print 4 times.

Of course you can also remove the sleep line, if that’s the case, all of code chunks on the global queue will be processed asynchronously and they will all finish in similar time to no sleep for any of them. It still holds that once ALL of them are finished, they will notify, and thus, the notify code blocks will run.

output

—– code execution entered dispatchGroup for index 0 ——
—– code execution entered dispatchGroup for index 2 ——
—– code execution entered dispatchGroup for index 3 ——
—– code execution entered dispatchGroup for index 1 ——
code execution 0 start
code execution 2 start
code execution 3 start
code execution 1 start
loop index 0—- code chunk 0—
loop index 1—- code chunk 0—
….
loop index 100—- code chunk 0—
code execution 0 finish

—— code execution left dispatchGroup for index 0 ——–
loop index 0—- code chunk 1—
loop index 0—- code chunk 2—
loop index 1—- code chunk 1—
loop index 0—- code chunk 3—
….
loop index 100—- code chunk 1—
code execution 1 finish

—— code execution left dispatchGroup for index 1 ——–
loop index 51—- code chunk 2—
loop index 35—- code chunk 3—
loop index 52—- code chunk 2—

loop index 68—- code chunk 3—
loop index 100—- code chunk 2—
code execution 2 finish

—— code execution left dispatchGroup for index 2 ——–
loop index 69—- code chunk 3—
loop index 70—- code chunk 3—
loop index 71—- code chunk 3—

loop index 98—- code chunk 3—
loop index 99—- code chunk 3—
loop index 100—- code chunk 3—
code execution 3 finish

—— code execution left dispatchGroup for index 3 ——–

Block 4
Block 4
Block 4
Block 4