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

NSConditionLockIs theNSConditionFor 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.