iOS gcd看我就够了

gcd是iOS中多线程的一种技术,下面我们来看看gcd的用法

同步&异步

同步

同步执行:字面意思,同步执行就是执行完任务1,再执行任务2任务1不执行完任务2就等着。
对应函数dispatch_sync,这个函数会把一个block加入到对应队列,只有block执行完,这个函数才会返回。因此block执行完之前,调用dispatch_sync的线程是阻塞的。代码如下:

    //dispatch_sync同步执行
    dispatch_sync(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
        NSLog(@"任务1");
    });
    NSLog(@"任务2");
iOS gcd看我就够了_第1张图片
同步效果

异步

对应函数dispatch_sync,同样该函数会把一个block添加到队列中。和同步执行不同的是,该函数会立即返回,不用等block执行完。

    //dispatch_async异步执行
    dispatch_async(dispatch_get_main_queue(), ^{
        NSLog(@"任务1");
    });
    NSLog(@"任务2");
iOS gcd看我就够了_第2张图片
异步执行效果

串行队列

通过DISPATCH_QUEUE_SERIAL修饰,或者主队列dispatch_get_main_queue,串行队列一定按照FIFO(先来后到的顺序)执行。串行队列中,执行当前任务时,该任务之前的人物都已执行完。对每一个串行队列,系统都会为这个队列创建唯一线程执行任务

并行队列

通过DISPATCH_QUEUE_CONCURRENT修饰,并行队列按照FIFO(先进先出)开始执行,注意是开始,结束时间是不确定的。并发队列中的任务:GCD会动态分配多条线程来执行。具体几条线程取决于当前内存使用状况,线程池中线程数等因素。

只有执行async异步任务才会开辟新线程,在async任务中:
1.主队列dispatch_get_main_queue下不会开辟线程,还是主线程;
2.串行队列开辟唯一线程;
3.并行队列开辟至少一条线程,系统自动分配;

死锁DeadLock

对应下面代码

1.首先aqueue是个串行队列,此时线程是主线程main thread;
2.在执行同步方法dispatch_sync后,会把block添加到aqueue队列,block不执行完之前,此时对应的线程main thread处于阻塞状态;
3.block内执行任务1dispatch_sync,而任务1dispatch_sync是添加在aqueue上的;
4.从上面我们知道此时aqueue对应的线程main thread处于阻塞状态,所以任务不会被执行,这就是死锁;

    //创建串行队列DISPATCH_QUEUE_SERIAL,注意dispatch_get_main_queue()s也是串行队列
    dispatch_queue_t aqueue = dispatch_queue_create("aqueue", DISPATCH_QUEUE_SERIAL);
    dispatch_sync(aqueue, ^{
        NSLog(@"这种情况会发生死锁:%@",[NSThread currentThread]);
        //任务1
        dispatch_sync(aqueue, ^{
            NSLog(@"任务1:%@",[NSThread currentThread]);
        });
        //任务2
        NSLog(@"任务2:%@",[NSThread currentThread]);
    });
iOS gcd看我就够了_第3张图片
死锁运行效果

从运行效果可以看出,block没走完(图片里停在44行),线程处于阻塞状态,在阻塞的线程里执行任务1,造成死锁。

死锁的另一种情况:

    dispatch_sync(dispatch_get_main_queue(), ^{
        NSLog(@"这种情况是死锁");
    });

代码内,默认是在主线程主队列下运行的,此时执行同步函数dispatch_sync,把block添加到主线程。我们上面知道同步函数dispatch_sync在串行队列(此时的主队列是串行队列)是阻塞线程的,也就是说主线程被阻塞了,此时block永远不会被执行,造成死锁。

这种情况为什么不发生死锁?

    //在主线程主队列下,在串行队列queue下添加同步任务
    dispatch_queue_t queue = dispatch_queue_create("serialQueue", DISPATCH_QUEUE_SERIAL);
    dispatch_sync(queue, ^{
    NSLog(@"这种情况不会发生死锁,因为此处任务是在一个新的队列里");
    });

死锁发生条件:在串行队列中,向该串行队列添加同步任务。(强调一下,是同一队列)

demo地址
未完待续~

你可能感兴趣的:(iOS gcd看我就够了)