Summary of basic principles of iOS

GCD, Grand Central Dispatch, is a C-based function that automatically takes advantage of more CPU cores and automatically manages thread life cycles

Summary: GCD is a function that adds a task to a queue and specifies its execution

function

There are two ways to perform tasks in GCD: synchronous function (dispatch_sync) and asynchronous function (dispatch_async).

Synchronization function (dispatch_sync)

  • Have to wait forThe next statement is executed only after the current statement completes, blocking the current thread
  • No new threads are created

Asynchronous functions (dispatch_async)

  • Don't have to wait forWhen the current statement completes, the next statement can be executed
  • withThe ability to initiate new threads, but not necessarily new threads, depending on the queue type specified by the current task

The queue

Dispatch queue is a kind of data structure, a special linear table, which is used to store the queue of tasks. In accordance with THE FIFO (first-in, first-out) principle, new tasks are always inserted to the end of the queue. Tasks are read from the front of the queue.

Serial queues

  • Only one task can be performed at a time
  • dispatch_queue_create("xxx", DISPATCH_QUEUE_SERIAL);Creating a serial queue
  • DISPATCH_QUEUE_SERIALYou can also useNULLInstead of
Dispatch_queue_t serialQueue1 = dispatch_queue_create(" com.cjl.queue ", NULL); dispatch_queue_t serialQueue2 = dispatch_queue_create("com.CJL.Queue", DISPATCH_QUEUE_SERIAL);Copy the code

Concurrent queue

  • Multiple tasks can be performed at the same time
  • dispatch_queue_create("xxx", DISPATCH_QUEUE_CONCURRENT);Creating concurrent queues
  • Only in theAn asynchronous functionOnly under the concurrent effect
Dispatch_queue_t concurrentQueue = dispatch_queue_create(" com.cjl.queue ", DISPATCH_QUEUE_CONCURRENT);Copy the code

The home side column

Main Dispatch Queue

  • specialSerial queues
  • Dedicated to theA serial queue that schedules tasks on the main thread, depends on the main program, the main Runloop, inThe main functionBefore the call
  • dispatch_get_main_queue()Gets the main queue
Dispatch_queue_t mainQueue = dispatch_get_main_queue();Copy the code

Global queue

Global Dispatch Queue

  • The GCD default concurrency queue

  • dispatch_get_global_queue(intptr_t identifier, uintptr_t flags); Gets the global concurrent queue

    • The first parameter saysQueue priority, the defaultDISPATCH_QUEUE_PRIORITY_DEFAULT=0After iOS9.0 was quality of servicequality-of-servicereplace
    • The second argument uses 0
Dispatch_queue_t globalQueue = dispatch_get_global_queue(0, 0); -dispatch_queue_priority_high -- QOS_CLASS_USER_INITIATED - DISPATCH_QUEUE_PRIORITY_DEFAULT -- QOS_CLASS_DEFAULT - DISPATCH_QUEUE_PRIORITY_LOW -- QOS_CLASS_UTILITY - DISPATCH_QUEUE_PRIORITY_BACKGROUND -- QOS_CLASS_BACKGROUNDCopy the code

In daily development, global queue + concurrent juxtaposition is usually used in this way

Dispatch_async (dispatch_get_global_queue(0, 0)) ^{dispatch_async(dispatch_get_main_queue(), ^{// return to main thread for UI}); });Copy the code

Serial queue + synchronization function

[Sequential execution of tasks] : Tasks are executed one after the other in the current thread without creating a new thread

Serial queue + asynchronous function

[Sequential execution of tasks] : Tasks are executed one after another, creating a new thread

Concurrent queue + synchronization function

[Sequential execution of tasks] : Tasks are executed one after another without opening up threads

Concurrent queue + asynchronous function

[Out-of-order execution of tasks] : Tasks are executed out of order, and new threads are created

Main queue + synchronization function

[Cause deadlock] : Tasks wait for each other, causing deadlock

Deadlock phenomenon

  • The main thread is waiting to execute the task first because of your synchronization function
  • The main queue waits for the main thread to complete before executing its own task
  • Main queue and main thread waiting on each other cause deadlock

Main queue + asynchronous function

[Sequential execution of tasks] : Tasks are executed one after another without opening up threads

Global concurrent queue + synchronization function

[Sequential execution of tasks] : Tasks are executed one after another without opening new threads

Global concurrent queue + asynchronous function

[Task out of order] : When a task is out of order, a new thread will be created

conclusion

Function \ queue Serial queues Concurrent queue The home side column Global concurrent queue
Synchronization function Execute sequentially without opening up threads Execute sequentially without opening up threads A deadlock Execute sequentially without opening up threads
An asynchronous function Sequential execution opens up threads Out of order execution, open up threads Execute sequentially without opening up threads Out of order execution, open up threads

Related interview questions

[Interview question 1] Asynchronous function + concurrent queue

- (void)interview01{dispatch_queue_t queue = dispatch_queue_create(" com.cjl.queue ", DISPATCH_QUEUE_CONCURRENT); NSLog(@"1"); Dispatch_async (queue, ^{NSLog(@"2"); dispatch_async(queue, ^{ NSLog(@"3"); }); NSLog(@"4"); }); NSLog(@"5"); } ---------- ----------- the output sequence is 1 5 2 4 3Copy the code

An asynchronous function opens a new thread, does not block the main queue,

Analysis of the
  • The mission of the main line isNSLog(1), asynchronous Block, NSLog(5)Because theNSLog(1)andNSLog(5)Is the same, andAsynchronous BlockIs more complex, soNSLog (1) and the NSLog (5)Prior to theAsynchronous Block
  • inAsynchronous BlockBy the same token,NSLog (2) and the NSLog (4)Prior to theAsynchronous Block.
  • inMain thread blockingOr in other extreme cases,NSLog(2)Have priorityNSLog(1)andNSLog(5)

[Interview question 2] Asynchronous function nested synchronous function + concurrent queue

- (void)interview02{dispatch_queue_t queue = dispatch_queue_create(" com.cjl.queue ", DISPATCH_QUEUE_CONCURRENT); NSLog(@"1"); // dispatch_async(queue, ^{NSLog(@"2")); // dispatch_sync(queue, ^{NSLog(@"3"); }); NSLog(@"4"); }); NSLog(@"5"); } ---------- ----------- the output sequence is 1 5 2 3 4Copy the code
Analysis of the
  • The analysis of task 1 and task 5 is the same as the previous interview, so the order of execution isTask 1. Task 5. Asynchronous block
  • Task 2 is executed first in an asynchronous block, because the synchronous function willBlocking threads, so the execution order isTask 2, Task 3, task 4

Asynchronous serial nesting Synchronous serial nesting

- (void)interview03{dispatch_queue_t queue = dispatch_queue_create(" com.cjl.queue ", NULL); NSLog(@"1"); // dispatch_async(queue, ^{NSLog(@"2")); // dispatch_sync(queue, ^{NSLog(@"3"); }); NSLog(@"4"); }); NSLog(@"5"); } ---------- ----------- is displayed in the following order: 1 5 2 Deadlock crashCopy the code
Analysis of the
  • Task 1. Task 5. Asynchronous blockThe order of execution is the same as analyzed above
  • inAsynchronous blockIn, first willTask 2,The synchronization block,Task 4Add to serial queue, wait to execute, serial queue in order of tasksTask 2 --> Synchronize block --> Task 4.
  • To start the execution, run it firstTask 2And then to performThe synchronization Block, because it is the same serial queue, will beTask 3Add inTask 4After, the sequence of tasks in the serial queueSynchronize block 4 --> Task 3.
  • Because the synchronization function willBlocking the current thread, soTask 4Waiting for theThe synchronization blockExecution completed, but now againSerial queuesFirst in, first out, soTask 3Waiting for theTask 4, resulting inA deadlock
  • A deadlockThere is a key stack of information_dispatch_sync_f_slow

Asynchronous function + synchronous function + concurrent queue

What is the order in which the following code is executed? A: 1230789 B: 1237890 C: 3120798 D: 2137890

- (void)interview04{dispatch_queue_t queue = dispatch_queue_create(" com.cjl. queue ", DISPATCH_QUEUE_CONCURRENT); Dispatch_async (queue, ^{NSLog(@"1"); }); dispatch_async(queue, ^{ NSLog(@"2"); }); Dispatch_sync (queue, ^{NSLog(@"3"); }); NSLog(@"0"); dispatch_async(queue, ^{ NSLog(@"7"); }); dispatch_async(queue, ^{ NSLog(@"8"); }); dispatch_async(queue, ^{ NSLog(@"9"); }); } ---------- prints the result ----------- in the order of :(1, 2, 3 out of order) 0 (7, 8, 9 out of order), it can be determined that 0 must be after 3, before 789Copy the code
Analysis of the
  • becauseTask 1, Task 2It’s asynchronous concurrency, it opens up new threads, so there’s no fixed order,
  • In the same way,Task 7, task 8, task 9There is no set order
  • becauseTask 3It’s synchronous concurrency, which blocks the current thread, soTask 3inTask 0It was executed before, soTask 0Will be inTask 3After that,Task 7, 8, 9before

There are several types of queues below

- Serial Dispatch Queue dispatch_queue_t serialQueue = dispatch_queue_create(" com.cjl.queue ", NULL); -concurrent Dispatch Queue dispatch_queue_t concurrentQueue = dispatch_queue_create(" com.cjl.queue ", DISPATCH_QUEUE_CONCURRENT); -dispatch Queue dispatch_queue_t mainQueue = dispatch_get_main_queue(); -global Dispatch Queue dispatch_queue_t globalQueue = dispatch_get_global_queue(0, 0);Copy the code

There are only two types of queues:

  • Concurrent queue:Concurrent queue (DISPATCH_QUEUE_CONCURRENT),Global concurrent queue (dispatch_get_global_queue)
  • Serial queue:Serial queue (DISPATCH_QUEUE_SERIAL \ NULL),Serial main queue (dispatch_get_main_queue)