One, foreword

Multithreading is very important knowledge together in iOS, I recently learned ming-jie li great god multithreaded related video, check for own multithreading knowledge as 20, benefit, in the simple record according to what they have learned, hoping to help more partners, also can be used as a fuzzy after check. This article is divided into two parts.

Two, the common multithreading scheme in iOS

Technical solution Introduction to the language Thread life cycle Use frequency
pthread A general purpose multithreaded API

Applicable to Unix/Linux/Windows systems etc

Cross-platform \ portable

Use is difficult
C Programmer management Almost no
NSThread Be more object oriented

Simple and easy to use, can directly operate the thread object
OC Programmer management Occasionally use
GCD The purpose of focus/focus is to replace threading technologies such as NSThread

Make full use of the multi-core equipment
C Automatic management
Often use \color{red}{often used}
NSOperation Based on GCD (bottom is GCD)

More simple and practical functions than GCD

Be more object oriented
OC Automatic management
Often use \color{red}{often used}

Two, synchronous, asynchronous, serial, concurrent

1. GCD has two functions to perform tasks

  • Perform tasks synchronously

dispatch_sync(dispatch_queue_t queue, dispatch_block_t block); Queue: indicates the queue. Block: indicates the task

2. GCD queues can be divided into two major types

  • \color{red}{Concurrent Dispatch Queue}

Can make multiple tasks concurrently \color{blue}{concurrent} concurrent (simultaneously) execution (automatically enable multiple threads to execute tasks simultaneously) concurrent \color{blue}{concurrent} concurrent function only in asynchronous \color{blue}{asynchronous} asynchronous (dispatch_ Async \color{blue}{async}async) function

  • Serial {color}{Serial} Serial Dispatch Queue

Let tasks be executed one after another (after one task is completed, the next task is executed)

  • Perform tasks asynchronously

dispatch_async(dispatch_queue_t queue, dispatch_block_t block);

  • GCD source: github.com/apple/swift…

3. Confusing terminology

  • There are four terms that are more confusing: synchronous, asynchronous \color{blue}{synchronous, asynchronous} synchronous, asynchronous, concurrent, serial \color{red}{concurrent, serial} concurrent, serial
  • Sync \color{blue}{sync} Sync and async \color{blue}{async} Async

\color{blue}{synchronization} synchronization: execute tasks in the current \color{green}{current} current thread, do not have \color{green}{do not have} do not have the ability to start a new thread \color{green}{new} new thread to execute tasks, with \color{green}{have} with the ability to start new threads

  • Concurrency and serialization have a major impact: how tasks are executed

Concurrent \color{red}{concurrent} concurrent: multiple \color{blue}{multiple} multiple tasks concurrent (simultaneously) execution serial \color{red}{serial} serial: one \color{blue}{one} After one task is completed, execute the next task

Dispatch_sync executes the task immediately on the current thread. \color{red}{is executed immediately in the current thread. } is executed immediately in the current thread. Dispatch_sync and dispatch_async are used to control whether new threads should be started.

The type of queue, which determines how the task is executed (concurrent, serial) 1, concurrent queue 2, serial queue 3, main queue (also a serial queue)

4. Execution effect of various queues:

Concurrent queue A manually created serial queue The home side column
Synchronization (sync)
There is no \ color {red} {not}
Starting a new thread


serial Serial} \ color {blue} {
Perform a task

There is no \ color {red} {not}
Starting a new thread


serial Serial} \ color {blue} {
Perform a task

There is no \ color {red} {not}
Starting a new thread


serial Serial} \ color {blue} {
Perform a task
Asynchronous (async)
There are \ color {green} {a}
Starting a new thread


concurrent \ color {orange} {and}
Perform a task

There are \ color {green} {a}
Starting a new thread


serial Serial} \ color {blue} {
Perform a task

There is no \ color {red} {not}
Starting a new thread


serial Serial} \ color {blue} {
Perform a task
  • Adding tasks to the current serial queue using sync will lock the current serial queue (deadlock)

5, problem,

Question 1:

The following code is executed on the main thread. Does this cause a deadlock?

- (void)viewDidLoad { [super viewDidLoad]; NSLog(@" execute task 1"); dispatch_queue_t queue = dispatch_get_main_queue(); Dispatch_sync (queue, ^{NSLog(@" execute task 2"); }); NSLog(@" execute task 3"); }Copy the code

Answer: Yes! The execution order is 1 crash.

Analysis:

1, the characteristics of queue: queue,FIFO(Fisrst In First Out)

2,dispatch_syncFeatures of a synchronous queue: Tasks are executed on the current thread immediately. Task 2 is executed synchronously and is in the main queue. whileviewDidLoadIt’s also in the main queue. So task 2 in the main queue will waitviewDidLoadThis task is done before it’s done, andviewDidLoadThis task is not complete until task 3 has been completed. Hence the deadlock.

As shown in the figure below:

Question 2:

The following code is executed on the main thread. Does this cause a deadlock? (change sync to async)

- (void)viewDidLoad { [super viewDidLoad]; NSLog(@" execute task 1"); dispatch_queue_t queue = dispatch_get_main_queue(); Dispatch_async (queue, ^{NSLog(@" execute task 2"); }); NSLog(@" execute task 3"); }Copy the code

Answer: No! The execution sequence is 132. Analysis: the main queue does not start a new thread, but the main queue does not start a new thread. The main queue does not start a new thread, but the main queue does not start a new thread.

Question 3:

The following code is executed on the main thread. Does this cause a deadlock?

- (void)viewDidLoad { [super viewDidLoad]; NSLog(@" execute task 1"); dispatch_queue_t queue = dispatch_queue_create("myqueue", DISPATCH_QUEUE_SERIAL); Dispatch_async (queue, ^{// Block 0 NSLog(@" execute task 2"); Dispatch_sync (queue, ^{// Block 1 NSLog(@" execute task 3"); }); NSLog(@" execute task 4"); }); NSLog(@" Execute task 5"); }Copy the code

Answer: Yes! Execution sequence is 152 crash. “Dispatch_sync” is used to complete tasks on the current thread immediately. \color{red}{is executed immediately in the current thread. } is executed immediately in the current thread. Comments in the code indicate Block0\color{blue}{Block 0}Block0 and Block1\color{green}{Block 1}Block1. Block0\color{blue}{Block 0}Block0 \color{blue}{Block 0}Block0 \color{green}{Block 1}Block1 (because it is sync) Block0\color{blue}{Block 0}Block0. To execute Block1\color{green}{Block 1}Block1, you must first execute Block0\color{blue}{Block 0}Block0 (FIFO). Block0\color{blue}{Block 0}Block0 and Block1\color{green}{Block 1}Block1 wait for each other, resulting in a deadlock.

Question 4:

The following code is executed on the main thread. Does this cause a deadlock?

- (void)viewDidLoad { [super viewDidLoad]; NSLog(@" execute task 1"); dispatch_queue_t queue = dispatch_queue_create("myqueue", DISPATCH_QUEUE_SERIAL); dispatch_queue_t queue2 = dispatch_queue_create("myqueue2", DISPATCH_QUEUE_CONCURRENT); Dispatch_async (queue, ^{// Block 0 NSLog(@" execute task 2"); Dispatch_sync (queue2, ^{// Block 1 NSLog(@" execute task 3"); }); NSLog(@" execute task 4"); }); NSLog(@" Execute task 5"); }Copy the code

Answer: No! The execution sequence is 15234. Block0\color{blue}{Block 0}Block0 \color{green}{Block 1}Block1 \color{green}{Block 1} Even if the questions are both serial queues, there will be no deadlock.

Question 5:

The following code is executed on the main thread. Does this cause a deadlock?

- (void)viewDidLoad { [super viewDidLoad]; NSLog(@" execute task 1"); dispatch_queue_t queue = dispatch_queue_create("myqueue", DISPATCH_QUEUE_CONCURRENT); Dispatch_async (queue, ^{// Block 0 NSLog(@" execute task 2"); Dispatch_sync (queue, ^{// Block 1 NSLog(@" execute task 3"); }); NSLog(@" execute task 4"); }); NSLog(@" Execute task 5"); }Copy the code

Answer: No! The execution sequence is 15234. Block0\color{blue}{Block 0}Block0 \color{green}{Block 1}Block1 \color{green}{Block 1}

  • Conclusion:

If you add a task to the current serial queue using sync, it will lock the current serial queue (creating a deadlock). Add task to current serial queue \color{red}{current} \color{blue}{serial};

6. Multi-threaded security risks

  • Resource sharing

A block of resource may be shared by multiple threads, that is, multiple threads may access the same block of resource \color{red}{multiple threads may access the same block of resource} Multiple threads may access the same block of resource, for example, multiple threads access the same object, the same variable, the same file.

  • When multiple threads access the same resource, it is easy to cause data disorder and data security \color{red}{data disorder and data security} data disorder and data security issues

7. Interview questions

Interview Question 1:

What is the printout of the following code?The printed result is:1, 3,

The reason:

1.
performSelector:withObject:afterDelay:
The essence of is toRunloopTo add a timer.

2, the child thread is not started by defaultRunloop. If you switch toperformSelector:withObjectThen the print result is132I don’t bring thisDelayIs notrunloopIs equivalent to a direct call.

The runloop code is not open source, so you can’t see the afterDelay implementation, so if you want to see it, you can look at GNUstep.

  • GNUstep

GNUstep is one of the GNU Project projects that re-open the OC library in Cocoa. Source address: www.gnustep.org/resources/d… Although GNUstep is not apple’s official source code, it still has some reference value.

Interview Question 2:

What is the printout of the following code?The printed result is:1 collapse

Analysis of the: in the implementationperformSelectorThe target thread had already exited, so it crashed. Can be found inblockIn the openrunloop:

[[NSRunLoop currentRunLoop] addPort:[[NSPort alloc] init] forMode:NSDefaultRunLoopMode];
[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
Copy the code

This will print 1 and 2. Because it starts a runloop, the thread doesn’t die after printing 1, the runloop sleeps, and then performSelector wakes up the Runloop to execute the test.

The above summary refers to and extracts the following articles. Thank you very much for sharing with the following authors! : Xiao Ma – Li Mingjie’s “Multithreading” course

Reprint please note the original source, shall not be used for commercial dissemination – fan how much