Multithreaded scheme
GCD
The common functions GCD have two functions for performing tasks
Execute dispatch_sync(dispatch_queue_t queue, dispatch_block_t block) tasks synchronously. Queue: queue block: tasks are performed asynchronously dispatch_async(dispatch_queue_t queue, dispatch_block_t block)Copy the code
The GCD queues
A Concurrent Dispatch Queue allows multiple tasks to execute concurrently (automatically enabling multiple threads to execute tasks simultaneously). The Concurrent function is only available under the dispatch_async function Queue) to Queue tasks one after another (after one task is finished, the next task is executed)Copy the code
Confusing terms
Synchronization and asynchrony Main effects are as follows: Can new threads be started? Synchronization: Tasks are executed in the current thread but new threads cannot be started. Asynchrony: Tasks are executed in a new thread and new threads can be started
Concurrency and serial execution Main effects: Task execution mode Concurrent: Multiple tasks are executed concurrently Serial: After one task is executed, the next task is executed
The execution effect of various queues
The interview questions
The first one is performSelector afterDelay
What is the following print?Answer: 1,3
- (void)performSelector:(SEL)aSelector withObject:(nullable id)anArgument afterDelay:(NSTimeInterval)delay
Copy the code
Reason: The method uses a timer inside and adds the timer to the Runloop, while the code is running in a child thread that has not opened Runloop and therefore cannot execute test
The second question
What to print below? Print 1 and crash
GNUstep
GNUstep, a project of the GNU Project, is an open-source re-implementation of the OC library in Cocoa
So after we initialize the thread, we call start, we execute the block, we print one, we continue, we call performSelector to execute the test task on the thread, but when the blCOk task is done, the thread exits and is destroyed, At this point, executing tasks in Thread is naturally impossible.
Source address: www.gnustep.org/resources/d…
Although GNUstep is not an official source code for Apple, it is a good reference
Scheduling group
Multi-thread security hazard
Resource Sharing A resource may be shared by multiple threads, that is, multiple threads may access the same resource. For example, multiple threads access the same object, the same variable, the same file. When multiple threads access the same resource, data corruption and data security issues can easily occur.
Solution: Use thread synchronization technology (synchronization, or coordinated pacing, in a predetermined order)
A common thread synchronization technique is locking
OSSpinLock
os_unfair_lock
pthread_mutex
dispatch_semaphore
dispatch_queue(DISPATCH_QUEUE_SERIAL)
NSLock
NSRecursiveLock
NSCondition
NSConditionLock
@synchronized
The difference between a spin lock and a mutex
When is it cost-effective to use a spin lock? Threads are expected to wait a short time for locks locking code (critical sections) is often called, but contention is rare. CPU resources are not tight for multicore processors
When is it cost-effective to use a mutex? It is expected that the thread will wait for a long time to lock. In the critical area of a single-core processor, IO operations exist. In the critical area, the code is complex or the number of cycles is large
OSSpinLock
1.OSSpinLock is called a “spin lock”. The thread waiting for the lock is in busy-wait state, occupying CPU resources
2. It is no longer secure, and priority inversion may occur
3. If the thread waiting for the lock has a higher priority, it will occupy CPU resources. The thread with a lower priority cannot release the lock
#import <libkern/ osatomic.h >
os_unfair_lock
Os_unfair_lock (mutex) os_unfair_lock (mutex) is used to replace insecure OSSpinLock. It is only supported in iOS10
2. Threads waiting for the OS_UNFAIR_LOCK lock are dormant, not busy
#import < OS /lock.h>
pthread_mutex
1. A mutex is called a mutex, and the thread waiting for the lock will sleep
#import <pthread.h>
It can also be used as a recursive lock (the same thread can repeatedly lock the same lock), allowing repeated locking
It can also be used as a conditional lock
NSLock, NSRecursiveLock
NSLock is a wrapper around a normal mutex lock and NSLock is also a mutex lock
NSRecursiveLock encapsulates a mutex recursive lock, and has the same API as NSLock
NSCondition
NSCondition is the encapsulation of mutex and COND
NSConditionLock
NSConditionLock
Is theNSCondition
For further encapsulation, specific conditional values can be set
dispatch_queue
dispatch_semaphore
Semaphore The initial value of a semaphore that can be used to control the maximum number of concurrent accesses by a thread. The initial value of a semaphore is 1, indicating that only one thread is allowed to access the resource at a time, ensuring that the threads are synchronized
@synchronized
@synchronized is the encapsulation of a mutex recursive lock
Objc-sync.mm file in objC4
@synchronized(obj) internally generates a recursive lock corresponding to OBj, and then locks and unlocks the lock
Poor performance, internal locking calls objc_sync_Enter. Unlocking will call objc_sync_exit, which internally uses the hash table structure. Find the index using the threaded @synchronized(obj) object objc as the key
The performance comparison
Os_unfair_lock OSSpinLock Dispatch_semaphore pthread_mutex dispatch_queue(DISPATCH_QUEUE_SERIAL) NSLock NSCondition pthread_mutex(recursive) NSRecursiveLock NSConditionLock @synchronized
atomic
Atomic is used to ensure atomicity of setter and getter properties. It is equivalent to adding thread synchronization locks to getter and setter properties. Internal checks are performed to see if atomic operations are performed, while non-atomic operations are performed directly
See objC4’s objc-accessors.mm
It does not guarantee that the process of using attributes is thread-safe
The assignment
The values
Read and write security schemes in iOS
Think about how to implement a scenario where only one thread can write at a time and multiple threads can read at a time and not both write and read at a time
The preceding scenario is a typical read/write scenario, which is often used for read/write operations such as files. In iOS, the solution is pthread_rwlock: read/write lock dispatch_barrier_async: asynchronous fence call
Pthread_rwlock The thread waiting for the lock goes to sleep
The dispatch_barrier_async function passes in a concurrent queue that must have been created by dispatch_queue_cretate itself. If a serial or global concurrent queue is passed in, this function is equivalent to the effect of dispatch_async.