多线程-GCD

01基本概念

iOS的多线程方案有哪几种?你更倾向于哪一种?

方案

他们底层其实都是依赖于pthread,更倾向于GCD

GCD常用函数

  • GCD中有2个用来执行任务的函数
    • 用同步的方式执行任务
      dispatch_sync(dispatch_queue_t queue, dispatch_block_t block);
      queue:队列
      block:任务
  • 用异步的方式执行任务
    dispatch_async(dispatch_queue_t queue, dispatch_block_t block);
    GCD源码:https://github.com/apple/swift-corelibs-libdispatch
  • GCD的队列可以分为2大类型
    • 并发队列(Concurrent Dispatch Queue)
      可以让多个任务并发(同时)执行(自动开启多个线程同时执行任务)
      并发功能只有在异步(dispatch_async)函数下才有效

    • 串行队列(Serial Dispatch Queue)
      让任务一个接着一个地执行(一个任务执行完毕后,再执行下一个任务),就算是异步函数也是一个接着一个

gcd带有create的也不要我们自己释放

GCD01

  • 有4个术语比较容易混淆:同步、异步、并发、串行
    同步和异步主要影响:能不能开启新的线程
    同步:在当前线程中执行任务,不具备开启新线程的能力
    异步:在新的线程中执行任务,具备开启新线程的能力

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

各种队列的执行效果

GCD02

死锁问题

以下代码会不会产生死锁
NSLog(@"任务1");
dispatch_queue_t mainQ = dispatch_get_main_queue();
dispatch_sync(mainQ, ^{
NSLog(@"任务2");
});
NSLog(@"任务3");
会产生死锁,
因为队列的特点就是排队FIFO,你把任务放到住队列里面,他会等前面的任务执行完,但是主队列中有一个任务了ViewDidLoad,又因为你是sync,希望立马在当前线程执行,执行完毕再往下执行。这样就造成了任务2和任务3之间相互等待。形成死锁

GCD-03

如果将sync改成async回会不会产生死锁
以下代码会不会产生死锁
NSLog(@"任务1");
dispatch_queue_t mainQ = dispatch_get_main_queue();
dispatch_async(mainQ, ^{
NSLog(@"任务2");
});
NSLog(@"任务3");
不会产生死锁。
如果用dispatch_sync会立马在当前线程执行任务,
如果用dispatch_async,不会要求在当前线程立马执行,是异步执行,等上一个任务执行完毕之后再执行。如果传的是并发队列,他会开启新的线程,

下面代码会不会产生死锁
//串行队列
dispatch_queue_t queue = dispatch_queue_create("myQueue", DISPATCH_QUEUE_SERIAL);
NSLog(@"任务1");
dispatch_async(queue, ^{ //0
NSLog(@"任务2");
dispatch_sync(queue, ^{//1
NSLog(@"任务3");
});
NSLog(@"任务4");
});
NSLog(@"任务5");
会产生死锁,因为block0的任务已经被添加到串行队列里面,block又是一个sync添加的任务,他是要求立即在当前线程执行任务,这样就造成了,block0等待队列重的block1任务执行,block1又要等待当前串行队列中之前正在执行的block0任务执行完毕之后才能呢执行,造成死锁

解决方法 开启另一个队列,这样就不用等待队列前面的任务执行完毕,就可以立即执行当前的任务,
//串行队列
dispatch_queue_t queue = dispatch_queue_create("myQueue", DISPATCH_QUEUE_SERIAL);
dispatch_queue_t queue3 = dispatch_queue_create("myQueue3", DISPATCH_QUEUE_SERIAL);
//并发队列
dispatch_queue_t queue2 = dispatch_queue_create("myQueue2", DISPATCH_QUEUE_CONCURRENT);
NSLog(@"任务1");

dispatch_async(queue, ^{ //0
    NSLog(@"任务2");
    NSLog(@"%@", [NSThread currentThread]);
    dispatch_sync(queue2, ^{//1
        NSLog(@"任务3");
        NSLog(@"%@", [NSThread currentThread]);
    });
    NSLog(@"任务4");
});
NSLog(@"任务5");

如果使用一个队列的话,可以使用一个并发队列,他也不会产生死锁,因为执行当前任务不用等前面的任务执行完毕,他们之间是并发执行的,可以同时执行多个任务

cgd04

  • 使用sync往当前串行队列添加任务,就会产生死锁,

不同方式获取的并发队列

dispatch_queue_t queue = dispatch_queue_create("myQueue", DISPATCH_QUEUE_CONCURRENT);
    NSLog(@"%@", queue);//<OS_dispatch_queue: myQueue[0x17416f780]>
    dispatch_queue_t queue1 = dispatch_queue_create("myQueue1", DISPATCH_QUEUE_CONCURRENT);
    NSLog(@"%@", queue1);//<OS_dispatch_queue: myQueue1[0x17416f900]>
    dispatch_queue_t queue2 = dispatch_get_global_queue(0, 0);
    dispatch_queue_t queue3 = dispatch_get_global_queue(0, 0);
    NSLog(@"%@", queue2);//<OS_dispatch_queue_root: com.apple.root.default-qos[0x100189500]>
    NSLog(@"%@", queue3);//<OS_dispatch_queue_root: com.apple.root.default-qos[0x100189500]>

06面试题01

以下代码的打印结果是什么
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" );
});
打印结果是:1、3
原因
performSelector:withObject:afterDelay:他的底层用到了NSTimer定时器,他的本质是往Runloop中添加定时器。子线程默认没有启动Runloop,所以不能执行
在主线程中是可以使用的,主线程中的runloop是默认开启的。

07-GNUstep

performSelector:withObject:afterDelay:这个方法的源码我们看不到,不开源。
GNUstep是GNU计划的项目之一,它将Cocoa的OC库重新开源实现了一遍
源码地址:http://www.gnustep.org/resources/downloads.php
虽然GNUstep不是苹果官方源码,但还是具有一定的参考价值
通过源码分析我们看到performSelector:withObject:afterDelay:这个方法底层就是往里面runloop里面添加了一个timer,所有我们只需要手动开起就可以了

08-面试题02

NSThread *thread = [[NSThread alloc] initWithBlock:^{
NSLog(@"1");
}];
[thread start];
[self performSelector:@selector(test) onThread:thread withObject:nil waitUntilDone:YES];

  • (void)test
    {
    NSLog(@"2");
    }
    结果,打印1 然后崩溃,因为子线程中的任务执行完就直接退出, 我们再给让他执行任务的时候他已经销毁了

09GCD队列组.

思考:如何用gcd实现以下功能
异步并发执行任务1、任务2
等任务1、任务2都执行完毕后,再回到主线程执行任务3

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值