This is the 12th day of my participation in the August More Text Challenge. For details, see: August More Text Challenge

Multithreading in iOS (part 1) – Processes and threads

Multithreading in iOS (Part 2) – Threads and locks

Multithreading in iOS (3) – Introduction to GCD

review

We got a first look at the queues and functions of GCD in the last post, so this post will continue.

1. Examples of different queues

Add a synchronization task to the main queue

  • Take a look at the following example 🌰
// Main queue synchronization
// Threads will not be opened
	NSLog(@"start");
    / / etc.
    dispatch_sync(dispatch_get_main_queue(), ^{
        NSLog(@"a");
    });
    NSLog(@"b");
Copy the code
  • The results

The program crashed. Why is that? The main queue is serial. Execution B must wait for execution A to complete, and execution A must wait for execution B to complete, thus waiting for each other, which is often called a deadlock.

The current code execution flow, by default, is the main queue, which is also a serial queue, and the tasks are executed in the following order:

NSlog (@ "start") -- - > dispathc_sync task blocks - > NSlog (@ "b")

When a task block is executed, a task NSlog(@”a”) is added to the main queue. The NSlog(@”a”) cannot be executed until the NSlog(@”b”) is executed, and the NSlog(@”b”) cannot be executed until the dispathc_sync task block is executed. The main queue then enters an associated wait state, which is a deadlock

Solution: Change main_queue to a serial queue or concurrent queue

  • Serial queue solution

  • Concurrency queue resolution

Add asynchronous tasks to the main queue

  • Add asynchronous tasks to the main queue

Asynchronous tasks added to the main queue will not block and will not collapse

Adding asynchronous tasks to concurrent queues

  • Add asynchronous functions to concurrent queues to execute tasks

Each task has the same complexity, and asynchronism does not block the main thread. The print order is a-e-B-D-C, and dispathc_async will start a new thread to execute the task

Adding a synchronization task to a concurrent queue

  • Add a synchronization function to the concurrent queue to perform the task

Although the queue is concurrent, the functions are synchronized, so the tasks are executed sequentially, so the print order is a-B-C-D-e, and synchronization is still not started

Add a synchronization task to a serial queue

  • The serial queue synchronization function performs the task

The serial queue synchronization function executes tasks in sequence and does not start new threads to execute tasks

Adding asynchronous tasks to a serial queue

  • The serial queue adds an asynchronous function to perform the task

Adding asynchronous function execution to a serial queue opens a new thread to execute tasks

Serial queues add a mixture of synchronous and asynchronous

  • Serial queues add a mixture of synchronous and asynchronous

This case is the same as adding a synchronization task to a main queue, which is also a serial queue. This case will also crash!

The execution of the “dispatch_sync” task block is not complete, and the execution of the “BB” task cannot be executed. Dd is waiting for the execution of the “BB” task. The execution of the “BB” task and the execution of the “DD” task wait for each other.

2. The GCD for example

Tasks are time consuming, as demonstrated by some examples

  • Create a concurrent queue

It took us 0.000010 seconds just to create a concurrent queue

  • Concurrent queue + asynchronous function
CFAbsoluteTime time = CFAbsoluteTimeGetCurrent(a);dispatch_queue_t queue = dispatch_queue_create("com.reno.cn", DISPATCH_QUEUE_CONCURRENT);// Concurrent queue
   / / asynchronous
    dispatch_async(queue, ^{
    });
	dispatch_async(queue, ^{
	});
	NSLog(@" time is %f".CFAbsoluteTimeGetCurrent()-time);
Copy the code
  • Print the result

Even if nothing is done, a function whose task is empty is time consuming, at 0.000036 seconds

  • It takes time to execute tasks inside a function

If a task is executed inside the function, the time is increased, but the print time is 0.000045 seconds

  • Concurrency + synchronization function

The concurrency + synchronization function takes 0.000366 seconds to execute

  • Create a serial queue

Creating a serial queue and creating a concurrent queue takes 0.000010 seconds

  • Serial + asynchronous function

Two tasks are executed in serial and asynchronous mode, taking 0.000032 seconds

  • Serial + synchronization function

The serial + synchronization function takes 0.000361 seconds to execute

  • The main thread performs the task

The following conclusions can be drawn from the above cases:

  • In any case, it takes time to execute a task, right
  • Asynchronous functions open threads and take less time to execute. In actual development, asynchronous functions can be used to solve concurrency, multithreading and other problems.

3. Queues in GCD

The home side column

1.The main queue: A built-in queue in which code is assigned to The main thread for execution. The Main queue can be obtained by calling dispatch_get_main_queue(). Because the main queue is related to the main thread, it is a serial queue, and the tasks handed in are executed in sequence (one task is executed before the next).

Global queue

2.Global queues: The entire application has three Global queues (the system has been created and only needs to be rebuilted. the queues are high, medium (default), and low. The queues can be accessed using dispatch_get_global_queue. Global queues are parallel queues that allow multiple tasks to execute concurrently (simultaneously) (automatically enable multiple threads to execute tasks simultaneously). The concurrency function is only valid under the asynchronous (dispatch_async) function.

Custom queue

3. Create your own queue: dispatch_queue_create the queue can be either serial or parallel, since the system already provides parallel, serial queues, so generally we do not need to create our own queue. A user can create any number of queues.

Note: The split thread cannot refresh the UI, only on the main thread. If every thread refreshes the UI, it will be easy to cause UI conflicts, and it will be out of sync, so only the main thread can refresh the UI to reduce the complexity and avoid conflicts as much as possible.

There are two main ways to return to the main thread in a split thread:

  1. performSeletorOnMainThread.
  2. usemain queue.

In previous versions, the autoRelease pool is not automatically created by the split thread, so you need to create the AutoRelease pool on the split thread. The current SDK version is no longer required. 2. The timer cannot be directly used in threads. You need to manually enable runloop. 3. If multiple threads modify the same resource (only reading variables, no problem), pay attention to thread synchronization issues.

conclusion

  • The synchronization function did not start a new thread
  • Async starts new threads (main queue + async does not start new threads)
  • The main queue is a special serial queue that is bound to the main thread

  • There are three types of queues in GCD: primary queue, global queue, and custom queue

The next article will continue the analysis of GCD

More to come

🌹 just like it 👍🌹

🌹 feel have harvest, can come a wave, collect + concern, comment + forward, lest you can’t find me next 😁🌹

🌹 welcome everyone to leave a message to exchange, criticize and correct, learn from each other 😁, improve self 🌹