IOS multithreading

1. How many multithreading schemes do iOS have?
  • NSOperation (based on GCD)

    • You can add task dependencies

    • Control of task execution status

      • IsReady indicates whether the current task isReady

      • IsExecuting Specifies whether the task is in the executing state

      • IsFinished Indicates whether the task is complete

      • IsCancelled whether the current mission isCancelled

      You can override the start and main methods to control the state.

      • If only the main method is overridden, the underlying control changes the task completion status and the task exits

      • If you override the start method, control the task state yourself

    • Maximum concurrency can be controlled

  • GCD

  • Pthread

  • NSThread

1.1 How do I Remove NSOperation isFinished = YES?

The state control of operation is realized through KVO

2. Understand concurrent queues, serial queues, synchronous queues, asynchronous queues

Queue: a first-in, first-out linear table. Both concurrent and serial queues execute tasks in first-in, first-out order.

  • Serial queue: Indicates that the tasks in a queue are executed sequentially, that is, one by one. The next task can be executed only after the previous task is completed.

  • Concurrent queue: Is also in accordance with the sequential tasks, difference, add to the concurrent queue have a, b, c, d four tasks, will perform a first, in the process of execution can perform b, therefore a and b which completes first is uncertain, specific can perform several at the same time, by the system control (cannot directly set the concurrency in the communist party, can be implemented by means of a semaphore, NSOperationQueue can be set directly), but is definitely called on a first-in, first-out basis.

  • Synchronization: Tasks are executed sequentially in the current thread. The next task can be executed only after the current task is completed. New threads are not started.

  • Asynchrony: A task is executed in a new thread, and the next task will proceed regardless of whether the called function (task) has completed its execution. And the ability to start new threads.

The difference between synchronous and asynchronous is whether to return immediately after adding tasks to the queue or wait until the added tasks are complete.

Concurrent queue Manually created serial queues Main queue (serial execution of tasks)
Synchronization (sync) No new thread/serial execution was started No new thread/serial execution was started No new thread/serial execution was started
Asynchronous (async) Start new threads or execute tasks concurrently Start new threads/serial execution of tasks Threading/serial execution of tasks is not enabled

Note: Adding tasks to the current serial queue using sync will lock the current serial queue (deadlock)

2. What does the following code do?
- (void)viewDidLoad {
    NSLog(@ "1");
    dispatch_queue_t queue = dispatch_queue_create("queue", DISPATCH_QUEUE_SERIAL);
    dispatch_sync(queue, ^{
        NSLog(@ "2");
    });
    NSLog(@ "3");
}
// It will not cause a deadlock
// Because 1, 3 and 2 are not in the same queue
Copy the code
- (void)interview01 {
    NSLog(@" Perform Task 1");
    dispatch_sync(dispatch_get_main_queue(),^{
        NSLog(@" Execute Task 2");
    });
    NSLog(@" Perform Task 3");
}
// Will cause a deadlock. Synchronous threads wait on each other.
// Cause: Task 2 was inserted into the synchronization queue before task 1 was completed.
// The normal synchronization queue should be executed after interview01 task completes
// The above process inserts the task 2 task and executes it immediately after completion, thus causing a deadlock.
Copy the code
- (void)interview02 {
    NSLog(@" Perform Task 1");
    dispatch_queue_t queue = dispatch_get_main_queue();
    dispatch_async(queue, ^{
        NSLog(@" Execute Task 2");
    });
    NSLog(@" Perform Task 3");
}
// Do not deadlock: the main queue executes tasks sequentially. But async is asynchronous, although no new threads are opened in the main queue
// However, in serial queues async tasks are not required to be executed immediately
// So answer: 1, 3, 2
Copy the code
- (void)interview03 {
    NSLog(@" Perform Task 1");
    dispatch_queue_t queue = dispatch_queue_create("myqueu", DISPATCH_QUEUE_SERIAL); // Serial queue
    dispatch_async(queue, ^{ / / 0
        NSLog(@" Execute Task 2");
        dispatch_sync(queue, ^{ / / 1
            NSLog(@" Perform Task 3");
        });
        NSLog(@" Execute Task 4");
    });
    NSLog(@" Execute Task 5");
}

// Will cause a deadlock
// In a serial queue, execute 1 then 5 then 2 since async is asynchronous
// In async, if you want to execute 3 synchronously, you must execute 4 first, but in queue, you must execute 3 first
// So it's deadlocked
Copy the code
- (void)interview04 {
    NSLog(@" Perform Task 1");
    dispatch_queue_t queue = dispatch_queue_create("myqueu", DISPATCH_QUEUE_SERIAL);
    dispatch_queue_t queue2 = dispatch_queue_create("myqueu2", DISPATCH_QUEUE_SERIAL); // Serial queue
    dispatch_async(queue, ^{ / / 0
        NSLog(@" Execute Task 2");
        dispatch_sync(queue2, ^{ / / 1
            NSLog(@" Perform Task 3");
        });
        NSLog(@" Execute Task 4");
    });
    NSLog(@" Execute Task 5");
}
Answer: 1, 5, 2, 3, 4
Copy the code
- (void)interview05 {
    NSLog(@" Perform Task 1");
    dispatch_queue_t queue = dispatch_queue_create("myqueu", DISPATCH_QUEUE_CONCURRENT);
    dispatch_sync(queue, ^{ / / 0
        NSLog(@" Execute Task 2");
        dispatch_sync(queue, ^{ / / 1
            NSLog(@" Perform Task 3");
        });
        NSLog(@" Execute Task 4");
    });
    NSLog(@" Execute Task 5");
}
// No deadlocks: Parallel queues can execute multiple tasks synchronously. Answer: 1, 2, 3, 4, 5
Copy the code
- (void)GCD {
    // Global queue: is the system development, directly to the (get) can be used; Similar to parallel queues, except that during debugging, the queue where the operation is located cannot be confirmed
    dispatch_queue_t queue = dispatch_get_global_queue(0.0);
    dispatch_async(queue, ^{
        NSLog(@ "1");
        [self performSelector:@selector(test) withObject:nil afterDelay:0];
        NSLog(@ "3");
    });
}
- (void)test {
    NSLog(@ "2");
}
// Print the result: 1 3
/ / performSelector: withObject: afterDelay: nature is added to the current RunLoop timing task.
// The child thread does not have RunLoop enabled by default. The thread is destroyed after execution 3
Copy the code
- (void)GCD2 {
    NSThread *thread = [[NSThread alloc] initWithBlock:^{
        NSLog(@ "1");
    }];
    [thread start];
    [self performSelector:@selector(test) onThread:thread withObject:nil waitUntilDone:YES];
}
// Crash
// thread, because the thread is not open RunLoop will be released after execution
/ / performSelector: onThread: withObject: waitUntilDone: can't find the thread will cause the crash
Copy the code

3. How to implement multiple read and write operations?

GCD dispatch_barrier

4. dispatch_group_async()

  1. Use GCD to achieve: A, B, C three tasks concurrent, after the completion of task D?
- (void)dispathcGroupAsync {
    dispatch_group_t group = dispatch_group_create();
    dispatch_group_async(group, _concurrent, ^{
        NSLog(@"A");
    });
    dispatch_group_async(group, _concurrent, ^{
        NSLog(@"B");
    });
    dispatch_group_async(group, _concurrent, ^{
        NSLog(@"C");
    });
    dispatch_group_notify(group, _concurrent, ^{
        NSLog(@"D");
    });
}
Copy the code

5. Multithreaded locks

Spin lock: A busy state occupies CPU resources while waiting for a lock

Mutex: Sleep while waiting for a lock

Conditional lock: open the conditional lock and continue to run. If the conditional lock does not meet the conditions, it goes to sleep

Recursive locking: Features can be repeatedly locked. reentrant

  • @synchronized

    Typically used when creating single-interest objects to ensure that the creation of objects in a multithreaded environment is unique

  • atomic

    Property keyword that performs atomic operations (not responsible for use) on the object being modified. For example, array = [NSMutableArray Array] assignments guarantee atomicity; [Array addObject:obj] object operations do not guarantee atomicity.

  • OSSpinLock

    It is a spin lock and is not secure at present. Priority inversion may occur. For example, if the thread waiting for a lock has a higher priority, it will continue to occupy CPU resources, and the thread with a lower priority cannot release the lock.

  • NSLock

    If the same lock is called twice, it will cause a deadlock. You can solve the problem of multiple lock operations by recursive locking, or you can use different locks.

  • NSRecursiveLock

    Recursive locking

  • Dispatch_semaphore_t semaphore

    Dispatch_semaphore_wait: blocks the thread and is an active action

    Dispatch_semaphore_singal: Awakening is a passive action

  • pthread_mutex

    Low-level locks, NSlocks and so on are basically implemented based on MUtex