iOS---多线程的一些注意点

本文是笔者通过前辈的指导,然后总结一些 IOS 多线程的注意点,总结的知识点不会太全面,希望读者们多多谅解。本文不会涉及到多线程三个工具的用法--- NSThread 、 GCD 、 NSOperation 。

NSThread

NSThread 相比 GCD 和 NSOperation ,其优点是更为轻量级的;
缺点就是需要自己去管理线程的生命周期,线程同步,为了避免多个线程访问并修改同一资源,还要加上互斥锁(性能消耗很大)。

所谓的轻量级,其实是指其代码库小,实现的功能少,但并不代表着性能消耗小,这是一个注意点。

少调用 NSThread 的 exit 方法

引用苹果官方文档的一句话

Invoking this method should be avoided as it does not give your thread a chance to clean up any resources it allocated during its execution.

翻译:应避免调用此方法,因为它不会让线程有机会清除其执行期间分配的任何资源。

前辈大佬给我举了个例子:如果线程正在执行文件操作,在没有关闭文件之前调用该方法,线程的入口函数就会立即被清空(可以理解为马上停止在线程中的操作,退出当前线程),文件没有关闭,导致内存崩溃。

NSThread 的 sleepUntilDate: 和 RunLoop 的 runUntilDate: 的区别

  • NSThread 的 sleepUntilDate: 线程在睡眠期间,任何事情都唤醒不了该线程,直到 Date 结束了,才会唤醒线程。
  • RunLoop 的 runUntilDate: runLoop 在睡眠期间,是有可能被其他事情唤醒的。

GCD

相比于 NSThread ,GCD 不需要我们去管理线程的生命周期,我们只是简单地往线程中添加操作就可以了,其他的事情 GCD 都会帮我们实行。


GCD 出现死锁的情况

-(void)text{
    
    NSLog(@"1");
    dispatch_sync(dispatch_get_main_queue(), ^{
        NSLog(@"2");
    });
    NSLog(@"3");
}

上面的情况就是串行队列里面同步提交当前串行队列导致死锁。
这个问题经过大佬的讲解,笔者一下子就通了。

解释: dispatch_sync同步函数是要等 Block 里面的内容执行完才会返回的。
上面的代码的执行顺序 : 输出1 --> dispatch_sync --> 输出3
执行到同步函数的时候,就会把 Block 追加的 3 的后面,即:
dispatch_sync --> 输出3 --> 输出2

上面构成的循环等待如下:
dispatch_sync 等待 输出2 (上面提到同步函数的特性)
输出2 等待 输出3
输出3 等待 dispatch_sync

即使没有输出3的这一步操作,还是有可能造成死锁,因为在主线程中有很多事情要做,所以难免会有其他事件像输出3那样插入在输出2之前,然后造成死锁。

dispatch_after

dispatch_after是延迟执行,这个的注意点在意延迟这个概念,不是延迟这行 Block 的代码(即执行线程中的操作),而是延迟**把Block 提交到队列当中 **,这个概念一定要注意。

你可能感兴趣的:(iOS---多线程的一些注意点)