美文网首页
多线程系列

多线程系列

作者: SeanLink | 来源:发表于2022-01-05 14:47 被阅读0次

    --------------------多线程--------------------

    你理解的多线程?

    iOS中的常见多线程方案

    技术方案 简介 语言 生命周期 使用频率
    pthread 一套通用的多线程API
    适用于Unix\Linux\Windows等系统
    跨平台\可移植
    使用难度大
    C 程序员管理 几乎不用
    NSThread 使用更加面向对象
    简单易用,可直接操作线程对象
    OC 程序员管理 偶尔使用
    GCD 旨在替代NSThread等线程技术
    充分利用设备的多核
    C 自动管理 经常使用
    NSOperation 基于GCD(底层是GCD)
    比GCD多了一些更简单实用的功能
    使用更加面向对象
    OC 自动管理 经常使用

    下面打印结果

    - (void)viewDidLoad{
        [super viewDidLoad];
        dispatch_queue_t que = dispatch_get_global_queue(0, 0);
        dispatch_async(que, ^{
            NSLog(@"1");
            [self performSelector:@selector(test) withObject:nil afterDelay:0];
            NSLog(@"3");
        });
    }
    - (void)test{
        NSLog(@"2");
    }
    

    打印结果为1,3.原因:
    performSelector:withObject:afterDelay:的本质是往Runloop中添加定时器
    子线程默认没有启动Runloop

    - (void)test{
        NSLog(@"2");
    }
    -(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
        NSThread *thread = [[NSThread alloc] initWithBlock:^{
            NSLog(@"1");
        }];
        [thread start];
        [self performSelector:@selector(test) onThread:thread withObject:nil waitUntilDone:YES];
    }
    

    会crash,因为新开的NSThread运行完之后就不可用了.除非在运行的时候开启它自己的NSRunLoop.那个线程会一直在那跑.

    NSRunLoop *currentRunLoop = [NSRunLoop currentRunLoop];
            [currentRunLoop runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
    

    GCD常用函数

    同步:dispatch_sync(dispatch_queue_t queue, dispatch_block_t block);
    异步:dispatch_async(dispatch_queue_t queue, dispatch_block_t block);

    并发队列:可以让多个任务并发(同时)执行,并发功能只有在异步(dispatch_async)函数下才有效
    串行队列:让任务一个接着一个地执行(一个任务执行完毕后,再执行下一个任务)

    同步、异步、并发、串行

    同步和异步主要影响:能不能开启新的线程:
    同步:在当前线程中执行任务,不具备开启新线程的能力
    异步:在新的线程中执行任务,具备开启新线程的能力

    并发和串行主要影响:任务的执行方式:
    并发:多个任务并发(同时)执行
    串行:一个任务执行完毕后,再执行下一个任务

    并发队列 手动创建的串行队列 主队列
    同步 没有开启新线程
    串行执行任务
    没有开启新线程
    串行执行任务
    没有开启新线程
    串行执行任务
    异步 有开启新线程
    并发执行任务
    有开启新线程
    串行执行任务
    没有开启新线程
    串行执行任务

    使用sync函数往当前串行队列中添加任务,会卡住当前的串行队列(产生死锁)

    队列组可使用在有任务依赖的地方:dispatch_group_t

    多线程的数据安全

    多线程的安全主要是通过在写的时候来加锁确保数据的安全,一般情况下都为多读单写,读写分离,读和写不可以同步进行.下面是关于锁的介绍:
    自旋锁: 等待锁的线程会处于忙等(busy-wait)状态,一直占用着CPU资源

    1. 目前已经不再安全,可能会出现优先级反转问题
    2. 如果等待锁的线程优先级较高,它会一直占用着CPU资源,优先级低的线程就无法释放锁
    3. 需要导入头文件#import <libkern/OSAtomic.h>

    互斥锁: 从底层调用看,等待os_unfair_lock锁的线程会处于休眠状态,并非忙等

    1. 需要导入头文件#import <os/lock.h>
    2. 用于取代不安全的OSSpinLock ,从iOS10开始才支持

    递归锁: 递归锁有一个特点,就是同一个线程可以加锁N次而不会引发死锁。但是需要成对出现

    Foundation系列:
    NSLock是对mutex普通锁的封装,NSRecursiveLock也是对mutex递归锁的封装,API跟NSLock基本一致,NSCondition是对mutex和cond的封装,NSConditionLock是对NSCondition的进一步封装,可以设置具体的条件值

    你都用过哪些锁(线程同步方案)?结合实际谈谈你是怎样使用的?
    性能从高到低:
    os_unfair_lock(互斥锁)
    OSSpinLock(自旋锁)
    dispatch_semaphore(信号量,设置为1代表只允许1条线程访问资源,保证线程同步)
    pthread_mutex(互斥锁,等待锁的线程会处于休眠状态.#import <pthread.h>)
    dispatch_queue(DISPATCH_QUEUE_SERIAL)(串行队列,实现线程同步)
    NSLock
    NSCondition
    pthread_mutex(recursive)
    NSRecursiveLock
    NSConditionLock
    @synchronized(是对mutex递归锁的封装)

    相关文章

      网友评论

          本文标题:多线程系列

          本文链接:https://www.haomeiwen.com/subject/qaahcrtx.html