(杂记)美团GCD经典面试题

960 阅读1分钟

题目

int a = 5;
while(a<5) {
    dispatch_async(dispatch_get_global_queue(0,0), ^{
        a++
    });
}

NSLog(@"a = %d", a);

哪里会报错?怎么改?

__block int a = 5;

⤵️

__block int a = 5;
while(a<5) {
    dispatch_async(dispatch_get_global_queue(0,0), ^{
        a++
    });
}

NSLog(@"a = %d", a);

__block做了什么?block本身底层实现是什么原理?

转载(海浪宝宝 iOS--block原理探究)

juejin.cn/post/684490…

会输出什么?为什么?

会输出a的值为 >=5; a是公共资源,在满足while条件的时候,很可能已经生成了不止5个的任务块。最后输出的a的值也不是a的真实值。因为打印a的值这个任务也是被插入这些任务块之中的。

如何得到a的真实值?

利用栅栏输出。 下面是GCD栅栏的几个实现。

栅栏有什么需要注意的

栅栏不能用在global全局并发队列里面,只能是自己创建的的并发队列。

为什么不能用下面的代码得到真实值?

__block int a = 5;
while(a<5) {
    dispatch_async(dispatch_get_global_queue(0,0), ^{
        a++
    });
}

 dispatch_async(dispatch_get_global_queue(0,0), ^{
        NSLog(@"a = %d", a);
    });

虽然根据FIFO打印任务是最后插入到队列的,但是因为

1.异步并发

2.任务块有自己的耗时操作

所以导致即便是最后插入也不能在所有任务都完成a++操作后最后输出

如何降低性能浪费?

dispatch_get_global_queue(0,0)底层实现

怎么才能输出为5?

这个代码还有哪些不足?

线程不安全。可以通过加锁来解决。 一般的代码习惯是先写一个nolock_的方法,然后在用lock锁住这个nolock的方法。(详细可以参照苹果源码)

当然也可以通过barrier来实现lock。