Painted levels: being fostered fostered fostered
Tags: “GCD” “Dispatch” “Semaphore” Author: 647 Review: QiShare team
* preface:
In the study of iOS performance Monitoring (2) – Main thread lag monitoring, we found that there are some GCD semaphore knowledge has not been combed before. GCD dispatch_semaphoRE_t *
Introduction to Semaphore
Semaphore is a safeguard in multithreaded environments that can be used to ensure that two or more critical code is not called concurrently.
Before entering a critical code section, the thread must acquire a semaphore. Once the execution is complete, the thread releases the semaphore. Wait for the next semaphore to be sent before the thread can continue to acquire the new semaphore and execute the key snippet again.
- Requirements:threadOne must be obtained before entering a critical code snippetA semaphore. (signal
signal
And such as signalwait
There should be one to one correspondence) - Function: Ensures that critical code segments are not called concurrently.
* Here’s an example:
There is only room for five cars in one parking lot. At that moment, six cars arrived. Only the first five go in. The sixth car waits until one of the cars leaves the lot before entering. Here, want to enter the parking lot – create a signal, there is currently a parking space, get the card – signal, there is no parking space, wait for the card – wait for the signal, leave the parking lot – destroy the signal. *
In general, semaphores have four operations.
- Initialization signal (
initialize
/create
) - Signal (
signal
/post
) - Signal (such as
wait
/suspend
) - Signal release (
destroy
)
GCD semaphore (dispatch_semphore_t)
In iOS development, the first thing that comes to mind is dispatch_semphore_t in GCD.
1. Create a semaphore
- Methods:
dispatch_semaphore_create(long value)
dispatch_semaphore_create(long value); / /! < Create semaphoreCopy the code
- Description:
parameter | instructions |
---|---|
value | The initial number of semaphore (>=0). Note: Passing a value less than zero will return NULL. |
If value > 0, a semaphore is created and the value signals are emitted simultaneously. If value = 0, it simply creates a semaphore without sending a signal. If value < 0, failure returns NULL.
2. Send semaphore
- Methods:
dispatch_semaphore_signal(dispatch_semaphore_t dsema);
dispatch_semaphore_signal(dispatch_semaphore_t dsema); / /! < Send semaphoreCopy the code
- Description:
parameter | instructions |
---|---|
dispatch_semaphore_t | The semaphore passed in for the signal to be sent. Dispatch_semaphore_t signal count +1. |
3. Wait for the semaphore
- Methods:
dispatch_semaphore_wait(dispatch_semaphore_t dsema, dispatch_time_t timeout);
dispatch_semaphore_wait(dispatch_semaphore_t dsema, dispatch_time_t timeout); / /! < Wait for semaphoreCopy the code
- Description:
parameter | instructions |
---|---|
dispatch_semaphore_t | The semaphore passed in for the signal to be waited for.dispatch_semaphore_t Signal count of -1. |
dispatch_time_t | Timeout waiting time. After that time, returns non-zero and executes directly down. It can also be set to DISPATCH_TIME_FOREVER Wait forever. |
The return value | instructions |
---|---|
Int | Returns 0 on success, non-0 on timeout. |
The application of semaphore
Use a semaphore to cause an “asynchronous” thread to complete a “synchronous” operation.
Even in multi-threaded concurrent scenarios, the synchronization of operations can be ensured by controlling semaphores.
For example: In general, we want to implement asynchronous threads to perform synchronous operations. There are two ways to do this:
1. The first: use serial queue + asynchronous operation.
In this case, only one sliver thread is opened and sequential operations are performed.
dispatch_queue_t queue = dispatch_queue_create("serial", DISPATCH_QUEUE_SERIAL);
dispatch_async(queue, ^{
NSLog(@"111:%@",[NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"222:%@",[NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"333:%@",[NSThread currentThread]);
});
Copy the code
This approach has some drawbacks:
First: since it is an asynchronous operation, a new child thread will be opened. It is also a serial queue, so only one sliver thread will be opened for synchronous operation. Lose the advantage of multithreading.
Second: you need to write it in a method, whereas in real development, you might asynchronously distribute it across methods, but you want to execute it serially.
2. The second kind: the use of semaphore, control of multi-threaded synchronization operation.
dispatch_semaphore_t sem = dispatch_semaphore_create(0); Dispatch_async (dispatch_get_global_queue(0, 0), ^{NSLog(@" task 1:%@",[NSThread currentThread]); dispatch_semaphore_signal(sem); }); dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER); Dispatch_async (dispatch_get_global_queue(0, 0), ^{NSLog(@" task 2:%@",[NSThread currentThread]); dispatch_semaphore_signal(sem); }); dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER); Dispatch_async (dispatch_get_global_queue(0, 0), ^{NSLog(@" task 3:%@",[NSThread currentThread]); });Copy the code
Of course, this is just an example. In practice, a signal and a wait are usually paired. Also, it is usually called separately in different methods.
For example, in iOS Performance Monitoring (2) – Main thread Lag monitoring, a signal will be sent when the main thread CommonModes change. At the same time, a sliver loop will be opened to continuously listen for CommonModes changes and wait for signals. In some cases, a timeout wait indicates that the main thread is currently stalled. Saving the current main thread method call stack serves monitoring purposes.
PS: detailed implementation, can be viewed in the QiLagMonitor source code.
Recommended articles:
Swift 5.1 (10) – Properties iOS App Background keep-active Use CGAffineTransform iN Swift iOS performance monitoring (1) — CPU power monitoring iOS performance monitoring (2) — Main thread lag monitoring iOS performance monitoring (3) — Add animation to the view with SwiftUI write a simple page with SwiftUI iOS App startup Optimization (3) — make your own tool to monitor the startup Time of the App — use “Time” “Profiler” tool monitoring App startup time iOS App startup optimization (a) – understand the App startup process qidance Weekly