Q&A

1. What are process and thread respectively?

  • Process:
    1. Process is a program with a certain independent function about a data set of a running activity, it is the basic unit of the operating system to allocate resources.
    2. Process refers to an application that is running in the system, which is the execution process of a program. We can understand it as an APP on a mobile phone.
    3. Each process is independent of each other, and each process runs in its own dedicated and protected memory space and has all the resources it needs to run independently
  • thread
    1. The smallest unit of the execution flow of a program. a thread is an entity within a process.
    2. A process must have at least one thread in order to execute a task. When an application starts, the system starts a thread, called the main thread, by default
  • The relationship between processes and threads
    1. A thread is the execution unit of a process in which all tasks of a process are executed
    2. Threads are the smallest unit of CPU allocation and scheduling
    3. A program can correspond to multiple processes (multi-process), a process can have multiple threads, but there must be at least one thread
    4. Threads within the same process share process resources

2. What is multithreading?

  • The realization principle of multithreading: in fact, a single CPU can only execute one thread at a time, multithreading is the CPU fast switching between multiple threads (scheduling), resulting in the illusion of multiple threads executing at the same time.
  • If you have a multi-core CPU you can actually handle multiple threads at the same time.
  • The purpose of multithreading is to complete multiple tasks synchronously and improve the efficiency of the system by improving the resource utilization rate of the system.

3. What are the advantages and disadvantages of multithreading?

  • Advantages:
    1. Can improve the execution efficiency of the program
    2. Appropriately improve resource utilization (CPU, memory utilization)
  • Disadvantages:

Open thread take up some memory space (by default, the main thread take up 1 m, the child thread take up 512 KB), if open a large number of threads, takes up a lot of memory space, and degrade the performance of the application thread, the more the greater the overhead of CPU on the thread scheduling Program design is more complicated: such as communication between threads, multi-threaded data sharing

4. What is the difference between concurrency and parallelism of multiple threads?

  • Parallelism: Take full advantage of the computer’s multiple cores to synchronize on multiple threads
  • Concurrency: Rapid switching on a thread that gives the impression of being synchronized

5. What are the characteristics of several schemes to achieve multi-threading in iOS?

  • Nsthreads are object-oriented and require the programmer to manually create threads, but not to manually destroy them. Communication between child threads is difficult.
  • GCD C language, make full use of the device multi-core, automatic management thread life cycle. It is more efficient than NSOperation.
  • NSOperation is packaged based on GCD, is more object-oriented, and has a few more features than GCD.

6. How to perform the next step after completing multiple network requests?

  • Use GCD’s dispatch_group_t

Create a dispatch_group_t dispatch_group_enter for each network request and then dispatch_group_leave for each callback. Enter and leave must be used together. Otherwise the group will always exist. After all blocks of “Enter” leave, blocks of “dispatch_group_notify” are executed.

NSString *str = @"http://xxxx.com/";
NSURL *url = [NSURL URLWithString:str];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
NSURLSession *session = [NSURLSession sharedSession];

dispatch_group_t downloadGroup = dispatch_group_create();
for (int i=0; i<10; i++) {
    dispatch_group_enter(downloadGroup);
    
NSURLSessionDataTask *task = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
        NSLog(@"%d---%d",i,i);
        dispatch_group_leave(downloadGroup);
    }];
    [task resume];
}

dispatch_group_notify(downloadGroup, dispatch_get_main_queue(), ^{
    NSLog(@"end");
});
Copy the code
  • Use GCD’s semaphore dispatch_semaphoRE_t

Dispatch_semaphore is a counter – based multi-threaded synchronization mechanism. If the semaphore count is greater than or equal to 1, count -1, return, and the program continues. If the count is 0, wait. “Dispatch_semaphore_signal” (semaphore) indicates counting +1 operations. “dispatch_semaphore_wait” (sema, DISPATCH_TIME_FOREVER) indicates waiting time. Create semaphore to 0, wait, wait for all 10 network requests to complete, dispatch_semaphore_signal(Semaphore) to count +1, then count -1 returns

NSString *str = @"http://xxxx.com/"; NSURL *url = [NSURL URLWithString:str]; NSURLRequest *request = [NSURLRequest requestWithURL:url]; NSURLSession *session = [NSURLSession sharedSession]; dispatch_semaphore_t sem = dispatch_semaphore_create(0); for (int i=0; i<10; i++) { NSURLSessionDataTask *task = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) { NSLog(@"%d---%d",i,i); count++; if (count==10) { dispatch_semaphore_signal(sem); count = 0; }}]; [task resume]; } dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER); dispatch_async(dispatch_get_main_queue(), ^{ NSLog(@"end"); });Copy the code

7. How to perform the next step after multiple network requests are executed sequentially?

  • Use semaphore

Each pass is dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER), at which point the thread waits and blocks the current thread until dispatch_semaphore_signal(sem) is called

NSString *str = @"https://juejin.cn/post/6969404087863345159/";
NSURL *url = [NSURL URLWithString:str];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
NSURLSession *session = [NSURLSession sharedSession];

dispatch_semaphore_t sem = dispatch_semaphore_create(0);
for (int i=0; i<10; i++) {
    
    NSURLSessionDataTask *task = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
        
        NSLog(@"%d---%d",i,i);
        dispatch_semaphore_signal(sem);
    }];
    
    [task resume];
    dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER);
}

dispatch_async(dispatch_get_main_queue(), ^{
    NSLog(@"end");
});
Copy the code

8. How to understand deadlocks in multiple threads?

A deadlock occurs when multiple threads (processes) are waiting for each other during execution because they are competing for resources. There are four necessary conditions for a deadlock to occur:

  • Mutually exclusive: A process uses the allocated resources exclusively. That is, only one process occupies a resource in a period of time. If another process requests the resource at this time, the requester can only wait until the process holding the resource is released.
  • Request and hold conditions: a process that has held at least one resource makes a new request for the resource that has been occupied by another process. In this case, the requesting process blocks but does not release other resources that it has obtained.
  • Inalienable conditions: Resources acquired by a process cannot be taken away until they are used up. They can only be released when they are used up.
  • Loop waiting condition: when a deadlock occurs, there must be a process — resource loop chain, that is, P0 in process set {P0, P1, P2, ··· Pn} is waiting for a resource occupied by P1. P1 is waiting for resources occupied by P2…… Pn is waiting for a resource that has been occupied by P0.
  • The most common combination is synchronization function + main queue, essentially queue blocking.
dispatch_sync(dispatch_get_main_queue(), ^{ NSLog(@"2"); }); NSLog(@"1"); // Do not print anything, just report an errorCopy the code

9. How to understand how GCD works?

  • The GCD has an underlying thread pool that houses individual threads. Called a pool, it is easy to understand that the threads in the pool are reusable and will be destroyed after a certain period of time when the thread is not called nonsense. Note: The number of threads to open is determined by the underlying thread pool (3~5 more threads are recommended). The pool is maintained automatically by the system, not by us programmers. What do we programmers need to care about? All we care about is adding tasks to the queue, and the queue schedules.
  • If synchronous tasks are stored in the queue, the underlying thread pool provides a thread for the task to execute after the task is queued. After the task is executed, the thread returns to the thread pool. So the tasks in the queue are scheduled over and over again, because it’s synchronous, so when we print currentThread, it’s the same thread.
  • Deposit if the queue is asynchronous tasks, asynchronous can open a thread (note), when the task after the team, the underlying thread pool will provide a thread for task execution, because be executed asynchronously, the queue tasks can schedule does not need to wait for the current task has been completed the next task, then the underlying thread pool will once again provide a thread for the second task, Return to the underlying thread pool after execution.
  • In this way, the thread completes a reuse, and does not need to open a new thread for each task execution, which saves the system overhead and improves efficiency. In iOS7.0, the GCD system can normally only open 58 threads, after iOS8.0, the system can open many threads, but in the development of applications, the recommended number of threads: 35 is the most reasonable.