# 24.任务与队列的几个面试题

### 一、 我们先看个面试题热热身

#### 面试题一 - 串行队列

下面的打印输出会是什么样？

```objc
/// 串行队列
dispatch_queue_t queue = dispatch_queue_create("Ryukie.Queue", DISPATCH_QUEUE_SERIAL);

dispatch_async(queue, ^{
    NSLog(@"1");
});

dispatch_async(queue, ^{
    NSLog(@"2");
});

dispatch_sync(queue, ^{
    NSLog(@"3");
});

NSLog(@"0");

dispatch_async(queue, ^{
    NSLog(@"7");
});

dispatch_async(queue, ^{
    NSLog(@"8");
});

dispatch_async(queue, ^{
    NSLog(@"9");
});
```

* A: 1230789
* B: 1237890
* C: 3120789
* D: 2137890

***分析***

* `3` 的同步任务，阻碍了`0 7 8 9` 的异步任务，故 `3` 一定在 `0 7 8 9` 前。
* `7 8 9` 三个任务的顺序不一定，但在 `0` 之后。
* `1 2 3` 的顺序不一定。

满足上面几点的答案为：A C

> 这里很可能会觉得 `12` 一定在 `3` 之前，要清楚 `3` 阻塞的是 `3` 之后的任务，`123` 的顺序并不一定。

***如果是异步队列呢？***

123 789 都是乱序的

#### 面试题二 - while

输出会是多少呢？

```C++
__block int num = 0;

while (num < 10) {
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        num++;
    });
}

printf("%d\n", num);
```

* 由于 num++ 是异步的，所以执行的次数大于等于 10
* 由于 while 循环条件阻塞，打印一定在 num >= 10 条件下输出
* 输出大于等于 10

![01](/files/-MiqFgyR5Myh3Db6OGNg)

#### 面试题三 - for

输出会是多少呢？

```C++
__block int num = 0;

for (int i = 0; i < 1000; i++) {
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        num++;
    });
}

printf("%d\n", num);
```

* for 循环保证了循环次数，一定是1000次
* for循环不会阻塞后面的 printf 函数执行
* 故：打印结果小于等于 1000（可能打印的时候还有 ++ 任务未执行完)

![02](/files/-MiqFgyTVfEbV1g11-qJ)

#### 面试题三 - 死锁

下面几个分别输出是什么

```C++
- (void)deadLock1 {
    //    dispatch_queue_t queue = dispatch_queue_create("Ryukie", NULL);
    dispatch_queue_t queue = dispatch_queue_create("Ryukie", DISPATCH_QUEUE_SERIAL);
    NSLog(@"1");
    dispatch_async(queue, ^{
        NSLog(@"2");
        dispatch_sync(queue, ^{
            NSLog(@"3");
        });
        NSLog(@"4");
    });
    NSLog(@"5");
}
```

* 输出
  * 1，5，2 死锁
* 分析
  * 串行队列
  * async 放入队列一个 blockA 任务
  * blockA 内部又向队列内部添加了一个 blockB 任务
  * 队列需要等待 blockA 执行完毕再执行下一个任务
  * 但是添加 blockB 时，sync 阻断了 blockA 内部的执行，导致 blockA 无法执行完成
  * 所以死锁了

```C++
- (void)deadLock2 {
    dispatch_queue_t queue = dispatch_queue_create("Ryukie", DISPATCH_QUEUE_CONCURRENT);
    NSLog(@"1");
    dispatch_async(queue, ^{
        NSLog(@"2");
        dispatch_sync(queue, ^{
            NSLog(@"3");
        });
        NSLog(@"4");
    });
    NSLog(@"5");
}
```

* 输出
  * 1，5，2，3，4

```C++
- (void)deadLock3 {
    //    dispatch_queue_t queue = dispatch_queue_create("Ryukie", NULL);
    dispatch_queue_t queue = dispatch_queue_create("Ryukie", DISPATCH_QUEUE_SERIAL);
    NSLog(@"1");
    dispatch_async(queue, ^{
        NSLog(@"2");
        dispatch_sync(queue, ^{
            NSLog(@"3");
        });
    });
    NSLog(@"5");
}
```

* 输出
  * 1，5，2 死锁
* 和第一个一样

```C++
- (void)deadLock4 {
    dispatch_queue_t queue = dispatch_queue_create("Ryukie", DISPATCH_QUEUE_SERIAL);
    NSLog(@"1");
    NSLog(@"2");
    dispatch_sync(queue, ^{
        NSLog(@"3");
    });
    NSLog(@"4");
    NSLog(@"5");
}
```

* 输出
  * 1，2，3，4，5
* 串行队列
  * 同步任务，没有阻塞队列内任务的执行，没有死锁，正常执行
  * 所以 同步任务 + 串行队列 不一定死锁

### 二、 任务与队列

![任务与队列](/files/-MiqFgyVXYZGrQHZnvDH)


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://ryukiedev.gitbook.io/wiki/ios/di-ceng/24.-ren-wu-yu-dui-lie-de-ji-ge-mian-shi-ti.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
