Multithreading (I)- Principle multithreading (II)-GCD foundation multithreading (III)-GCD function multithreading (IV)-GCD timer

The basic concept

thread

A thread is the basic execution unit of a process. All tasks of a process are executed in a thread. In order for a process to execute a task, it must have a thread. By default, the program starts a thread, which is called the main thread or UI thread.

process

A process is an application that is running in the system. Each process is independent of each other, and each process runs in its own dedicated and protected memory.

The relationship between threads and processes

  • Address space: Threads of the same process share the address space of the same process, while processes are independent of each other.
  • Resource ownership: Threads in the same process share resources such as memory,I/O,cpuEtc., but resources between processes are independent.
  • The crash of one process in protected mode does not affect other processes, but the crash of one thread kills the entire process. So multi-processing is more robust than multi-threading.
  • Process switchover consumes large resources and is efficient. So when it comes to frequent switching, threads are better than processes. Also, if you require concurrent operations that share variables at the same time, use threads instead of processes.
  • Execution process: Each independent process has a program run entry, sequential execution sequence, and program entry. However, the thread cannot be executed independently and must be dependent on the application, which provides multiple thread execution control.
  • Threads are the basic unit of processor scheduling, but processes are not.

For example, there is a process is to clean the classroom, which sweep the floor, wipe the table, wipe the glass, wipe the blackboard are different threads.

Principle of multithreading

The CPU switches between threads in a unit time slice.

The life cycle of a thread consists of five phases: create, prepare, run, block, and destroy.

  • New: Creates a thread
  • Ready: of the calling threadstart()Method, while the thread is waitingCPUIn the resource allocation phase, who took the first shotCPUResource, who starts execution.
  • Run: When a thread is scheduled and retrievedCPUResource, then enters the running state,runMethod defines the operations and functionality of a thread.
  • Blocking: At run time, a running thread may be blocked for some reason, such assleep(),wait()The thread is then blocked, and some other mechanism is needed to wake up the blocked thread, such as a callnotifyornotifyAll()Methods. The awakened thread does not execute immediatelyrunMethod, they have to wait againCPUThe resource is allocated to the running state. Destroy: If a thread completes normal execution or is forced to terminate prematurely or an exception causes the thread to terminate, then the thread is destroyed, freeing resources.

The whole process is as follows:

Multithreading is done through a thread pool, adding tasks to a queue and then starting them automatically after a thread is created. The threads in the thread pool are background threads. Each thread has a default stack size, runs at a default priority, and is in a multithreaded cell. The thread pool

There are four saturation policies, all of which implement the RejectedExecutionHandler interface:

  • AbortPolicyDirect sellingRejectedExecutionExeceptionException to prevent the normal operation of the system
  • CallerRunsPolicyRoll back the task to the caller
  • DisOldestPolicyDrop the most waiting task
  • DisCardPolicyDrop the task directly

Advantages and disadvantages of multi-threading

Advantages:

  • Can improve the execution efficiency of the program
  • Can improve the utilization of resources (CPU, memory)
  • The task on the thread is automatically destroyed after it completes execution

Disadvantages:

  • Starting threads takes up a certain amount of memory (512 per thread by default)KB)
  • If a large number of threads are enabled, a large amount of memory space will be occupied and the performance of the program will be reduced
  • The more threads,CPUThe more overhead there is on the calling thread
  • The program design is more complex, such as communication between threads, multithreaded data sharing

iOSMultithreading technology

IOS multithreading has many technologies, here is a comparison:

By comparison, we still mainly use GCD and NSOperation.

Threads andrunloopThe relationship between

  • runloopIt’s one to one with threads, onerunloopCorresponds to a core thread. Why is it core, becauserunloopCan be nested, but there can only be one core, and their relationships are stored in a global dictionary.
  • runloopIs to manage threads, when threadsrunloopWhen enabled, the thread will go to sleep after completing the task and will be woken up to execute the task.
  • runloopIs created on the first fetch and destroyed at the end of the thread.
  • For the main thread,runloopIt is created by default as soon as the program starts.
  • For child threads,runloopIt is lazy to load and is only created when we use it, so be careful when using a timer on a child thread to make sure that the child threadrunloopWas created, or the timer will not be called back.

Communication between threads

Communication between multiple threads, in addition to the simple access to the main thread, there are two ways.

  1. performSelector:onThread. For example there areA,BTwo threads, we can inAThread using this method, callBAnd then again in theBThe thread uses this method callAThread method, thus realizing communication between threads.
- (void)performSelectorOnMainThread:(SEL)aSelector      
                         withObject:(nullable id)arg
                         waitUntilDone:(BOOL)wait

- (void)performSelector:(SEL)aSelector 
               onThread:(NSThread *)thr 
               withObject:(nullable id)arg waitUntilDone:(BOOL)wait
Copy the code
  1. NSPort.NSPortThe method used is registered in the receiving threadNSPort, and use this in another threadportSends a message, the registered thread receives the message, and eventually calls a callback function in the main thread.

NSPort has three subclasses: NSSocketPort, NSMessagePort, and NSMachPort. However, only NSMachPort is available on iOS.

The NSMachPort mode is as follows:

  • 2.1 createAThe threadportThat will beportjoinrunloop
@property (nonatomic, strong) NSPort *aPort; @property (nonatomic, strong) TPerson *person; Self. aPort = [NSMachPort port]; self.aPort = [NSMachPort port]; Self.aport. delegate = self; self.aport. delegate = self; / / 3. Add the port to runloop, receiving port news [[NSRunLoop currentRunLoop] addPort: self, aPort forMode: NSDefaultRunLoopMode]; self.person = [[TPerson alloc] init]; [NSThread detachNewThreadSelector:@selector(personLaunchThreadWithPort:) toTarget:self.person withObject:self.aPort];Copy the code
  • 2.2 inpersonClass to create a response thread
@interface TPerson : NSObject - (void)personLaunchThreadWithPort:(NSPort *)port; @end #import "TPerson.h" @interface TPerson() @property (nonatomic, strong) NSPort *bPort; @ end @ implementation TPerson - (void) personLaunchThreadWithPort: (port {@ autoreleasepool NSPort *) {/ / set the child thread name [[NSThread  currentThread] setName:@"TPersonThread"]; // enable runloop [[NSRunLoop currentRunLoop] run]; // Create your own port self.bPort = [NSMachPort port]; / / complete the port to send the message to the main thread NSData * data = [@ "portPass" dataUsingEncoding: NSUTF8StringEncoding]; NSMutableArray *array =[[NSMutableArray alloc]initWithArray:@[data,self.bPort]]; // Send message to thread A // First argument: send time. // msgid message id. // components, send messages with parameters. // Reserved: number of bytes reserved for the header [port sendBeforeDate:[NSDate date] MSgid :10086 Components :array from: self.bport reserved:0]; }}Copy the code
  • 2.3 inAProxy method implemented by the thread to get information about the callback
#pragma mark - NSMachPortDelegate - (void)handlePortMessage:(NSPortMessage *)message{ NSLog(@"VC == %@",[NSThread currentThread]); NSLog(@" pass some information from person :"); // NSLog(@"localPort == %@",[message valueForKey:@"localPort"]); // NSLog(@"remotePort == %@",[message valueForKey:@"remotePort"]); // NSLog(@"receivePort == %@",[message valueForKey:@"receivePort"]); // NSLog(@"sendPort == %@",[message valueForKey:@"sendPort"]); // NSLog(@"msgid == %@",[message valueForKey:@"msgid"]); // NSLog(@"components == %@",[message valueForKey:@"components"]); NSArray *messageArr = [message valueForKey:@"components"]; NSString *dataStr = [[NSString alloc] initWithData:messageArr.firstObject encoding:NSUTF8StringEncoding]; NSLog(@" pass some information :%@",dataStr); NSPort *destinPort = [message valueForKey:@"remotePort"]; if(! destinPort || ! [destinPort isKindOfClass:[NSPort class]]){NSLog(@" error "); [destinPort isKindOfClass:[NSPort class]]){NSLog(@" error "); return; }}Copy the code

Tips

atomicwithnonatomic

  • nonatomicNon-atomic, non-thread-safe, but high performance, suitable for mobile devices with small memory
  • atomicAtomic attributes (thread-safe), designed for multithreading, are the default. Ensure that only one thread can write at a time (but multiple threads can write at a time), in the propertysetterMethod to add a lock (spin lock). Single-write multi-read: A single thread writes data and multiple threads can read data. But it consumes a lot of resources.

In general iOS development, there are some things to note about thread-specific:

  • Try to declare all attributes asnonatomic
  • Try to avoid multiple threads grabbing the same resource
  • Try to transfer the service logic of locking and resource snatching to the server to reduce the pressure on mobile clients