Processes and threads

1.1 process

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

1.2 the thread

A thread is the basic execution unit of a process. All tasks in a process are executed in a thread. Therefore, there must be at least one thread in a process. By default, iOS apps start a main thread, also known as the UI thread.

1.3 Relationship between processes and threads

  • Address space: The address space in the same process can be shared by multiple threads in the same process, but the address space between processes is independent
  • Resource ownership: Resources in the same process can be shared by all threads in the process, for examplememory,I/O,CUPAnd so on, but resources between processes are independent of each other
  • The crash of any thread in a process can cause the entire process to crash, but the crash of a process does not affect another process
  • A process can be seen as a container for threads. Each process has an entry point for the program to run, but threads cannot run independently and must depend on the process

1.4 the thread andRunloopThe relationship between

  • threadwithRunloopIt’s one to one, oneRunloopCorresponds to aCore threadWhy is it core? BecauseRunloopCan be nested, but there is only one core, and their correspondence is stored in a global dictionary
  • RunloopIt is used to manage threads. When they finish executing a task, they go to sleep and wake up when a task comes in and start executing it (event-driven).
  • RunloopIt is created on the first fetch and destroyed at the end of the thread
  • The main thread of theRunloopIt is created by default when the program starts
  • The child threadRunloopIs lazy-loaded and is created only when used, so used in child threadsNSTimerTake care to ensure that the child threadRunloopCreated otherwiseNSTimerIt won’t go into effect.

1.5 Thread life cycle

The life cycle of a thread can be divided into five phases: new, ready, invoked, blocked, and dead.

multithreading

2.1 Concepts and Principles

A process can be concurrent with multiple threads to perform their respective tasks at the same time, called multithreading. Time-sharing operating system will reduce the CPU time length is divided into basic same time interval, the name is “time”, in a time slice, the CPU can only handle one thread of a task, for a single core CPU, in different time to perform the tasks in different threads, are formed multiple tasks at the same time perform “illusion” :

2.2 Multithreading commonly used in ios

In iOS, there are several ways to use multithreading:

1. Pthread: POSIX Thread, short for PThread, is the POSIX standard of threads. It is a set of universal multithreading API, which can be used cross-platform on Unix, Linux, and Windows platforms. It’s basically not used in iOS.

2.NSThread: An object-oriented thread class packaged by Apple, which can directly operate threads. Compared with GCD, NSThread is more efficient and is created by programmers themselves. Use frequency is low.

3.GCD: Grand Central Dispatch, realized by C language, is a solution proposed by Apple for multi-core parallel computing. CGD will automatically utilize more CPU cores and automatically manage the life cycle of threads. GCD is also the most used multi-threading technology on iOS.

4.NSOperation: Object-oriented multithreading technology encapsulated based on GCD, often used with NSOperationQueue, high frequency of use.

The thread pool

  • Thread PoolA pool that manages the life cycle of multiple threads. There is no direct contact with thread pools in iOS development, because GCD already includes management of thread pools, and we just need threads from GCD to perform tasks.
  • The life cycle of a threadThe life cycle of a thread includescreatereadyrundeathWith these four phases, we can control the life cycle of the thread by blocking, exiting, and so on.

Communication between threads

4.1 Communication modes between several threads

  • Direct messaging: This is very familiar –performSelector: series.
  • Global variables...: Direct passageglobalVariables,The Shared memoryAnd so on, but this way will cause resource grab, involving thread safety issues.
  • The Conditions:A special type of lock, the conditional lock, is used to make a thread wait, and the thread blocks and goes to sleep. When a single is sent to the same conditional lock in another thread, the waiting thread is awakened to continue executing the task.
  • Run loop sources: CustomizeRun loop sourcesThis will be studied separately in a later articleRun loop.
  • Ports and sockets: Implements thread communication through ports and sockets.

4.2 Example of communication between threads

  • First create the port in the main thread, set up the proxy, and then add the port to the Runloop to start the child thread.
- (void)viewDidLoad {
    [super viewDidLoad];
    self.title = @"Port thread communication"; self.view.backgroundColor = [UIColor whiteColor]; Self. MyPort = [NSMachPort]; self. MyPort = [NSMachPort]; Self.myport.delegate = self; self.myport.delegate = self; [[NSRunLoop currentRunLoop] addPort:self.myPortforMode:NSDefaultRunLoopMode];
    
    self.person = [[KCPerson alloc] init];
    [NSThread detachNewThreadSelector:@selector(personLaunchThreadWithPort:)
                             toTarget:self.person
                           withObject:self.myPort];
    
}
Copy the code
  • Here, the child thread sends a message to the main thread through Port.
- (void)personLaunchThreadWithPort:(NSPort *)port{
    
    NSLog(@"VC responds to Person"); Autoreleasepool {//1. Save the mainline port self.vcPort = port; //2. Set the name of the child thread [[NSThread currentThread]setName:@"KCPersonThread"]; Runloop [[NSRunLoop currentRunLoop] run]; // create self port self.myPort = [NSMachPort port]; Self.myport.delegate = self; self.myport.delegate = self; //6. Finish sending the message to the main thread port [self sendPortMessage]; }} /** * sendPortMessage {NSData *data1 = [@"Gavin" dataUsingEncoding:NSUTF8StringEncoding];
    NSData *data2 = [@"Cooci"dataUsingEncoding:NSUTF8StringEncoding]; NSMutableArray *array =[[NSMutableArray alloc]initWithArray:@[data1,self.myPort]]; // Send a message to the main thread of the VC // first argument: send time. // msgid message id. // components, send messages with parameters. / / reserved: Number of bytes reserved for the header [self.vcPort sendBeforeDate:[NSDate Date] MSgid :10086 Components :array from: self.myport reserved:0]; }Copy the code
  • The main thread takes the data and sends a message to the child thread.
- (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"]); //NSLog(@) does not have this hidden attribute"from == %@",[message valueForKey:@"from"]);
    
    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(@"The data sent was wrong.");
        return;
    }
    
    NSData *data = [@"VC received!!!!!!"dataUsingEncoding:NSUTF8StringEncoding]; NSMutableArray *array =[[NSMutableArray alloc]initWithArray:@[data,self.myPort]]; // Very important, if you want to receive information in Person's port, you must add runloop [[NSRunLoop currentRunLoop] addPort:destinPort to the current main threadforMode:NSDefaultRunLoopMode];
    
    NSLog(@"VC == %@",[NSThread currentThread]);
    
    BOOL success = [destinPort sendBeforeDate:[NSDate date]
                                        msgid:10010
                                   components:array
                                         from:self.myPort
                                     reserved:0];
    NSLog(@"%d",success);

}

Copy the code
  • The child thread receives the message sent by the main thread
- (void)handlePortMessage:(NSPortMessage *)message{
    
    NSLog(@"person:handlePortMessage == %@",[NSThread currentThread]);


    NSLog(@"Some information from VC :");
    NSLog(@"components == %@",[message valueForKey:@"components"]);
    NSLog(@"receivePort == %@",[message valueForKey:@"receivePort"]);
    NSLog(@"sendPort == %@",[message valueForKey:@"sendPort"]);
    NSLog(@"msgid == %@",[message valueForKey:@"msgid"]);
}
Copy the code

At this point, the example of communication between threads via port is complete.