Exemplo 1
- (void)surpassNum
{
while (self.num < 500) {
dispatch_async(dispatch_get_global_queue(0, 0), ^{
self.num++;
});
}
NSLog(@"num is %d",self.num);
}
复制代码
Resultado : O resultado da impressão é >=500
Análise :
-
Ao entrar no loop pela primeira vez, self.num = 0, e uma tarefa assíncrona é criada neste momento, mas essa tarefa não é necessariamente executada imediatamente, ela aguardará o agendamento de primeira saída e, em seguida, entrará no Como a tarefa é executada, então self.num++ não é executado, então no segundo loop, self.num ainda é igual a 0, e uma nova tarefa assíncrona será criada neste momento, e assim por diante, pelo menos 500 tarefas assíncronas serão comuns.
-
Como self.num<500 é usado como condição de término no loop while, somente quando self.num >=500 ele pode sair do loop e imprimir
-
No meio do salto para fora do loop para executar a impressão, pode haver várias tarefas assíncronas executadas, o que equivale a self.num++ sendo executado N vezes
-
Portanto, o resultado da impressão deve ser >=500
Extensão: Se dispatch_async for substituído pela tarefa de sincronização dispatch_sync, o resultado da impressão deverá ser 500, pois a tarefa de sincronização bloqueará o encadeamento e o próximo loop não poderá ser executado até que self.num++ seja executado.
Exemplo 2
- (void)fixNum
{
for(int i= 0; i < 1000; i++){
dispatch_async(dispatch_get_global_queue(0, 0), ^{
self.num++;
});
}
NSLog(@"fix num is %d", self.num);
}
复制代码
Resultado : Imprimir resultado 0-999 Análise :
-
O loop for é usado aqui, e a variável temporária i é usada em vez de self.num para julgamento. Self.num não tem nada a ver com o loop, então apenas 999 loops são executados aqui, ou seja, 999 tarefas assíncronas são criadas.
-
Quando i== 1000, o loop for termina. Embora 999 tarefas assíncronas sejam criadas neste momento, essas tarefas são concluídas? Obviamente não, ele precisa aguardar o agendamento da thread; então, antes de imprimir, quantas tarefas podem ser executadas? , isso é incerto, talvez uma tarefa não tenha sido executada, talvez todas executadas, então o resultado da impressão pode ser 0-999
-
Embora seja teoricamente 0-999, o resultado da impressão ainda será próximo a 999
Exemplo 3
- (void)asynDemo
{
dispatch_queue_t queue = dispatch_queue_create("com.qihu", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(queue, ^{
NSLog(@"1");
});
dispatch_async(queue, ^{
NSLog(@"2");
});
dispatch_sync(queue, ^{
NSLog(@"3");
});
NSLog(@"0");
dispatch_async(queue, ^{
NSLog(@"4");
});
dispatch_async(queue, ^{
NSLog(@"5");
});
dispatch_async(queue, ^{
NSLog(@"6");
});
}
复制代码
P: Qual é a possível razão para a impressão acima?
- R: 1230456
- B: 1234560
- C: 3120465
- D: 2134560
答: A和C 分析
- 任务3为同步任务,同步任务有个特性就是会阻塞线程的执行,所以在任务3未执行完毕之前,任务0以及之后的任务都会处于阻塞状态,所以3必定在0之前打印
- 然后根据函数的按顺序执行的规律,任务0必定会在 4、5、6 之前进行打印
- 异步任务之间是无序的,所以 1、2、3 之间顺序不定,4、5、6 之间顺序也是不定
如果 queue 是 DISPATCH_QUEUE_SERIAL 类型的串行队列的话则答案是 A
示例4
- (void)barrierTest
{
dispatch_queue_t queue = dispatch_queue_create("com.barrier", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(queue, ^{
NSLog(@"1");
});
dispatch_async(queue, ^{
NSLog(@"2");
});
dispatch_barrier_async(queue, ^{
NSLog(@"3");
});
dispatch_async(queue, ^{
NSLog(@"4");
});
}
复制代码
结果:
1234 或 2134
分析:
- queue 是一个 DISPATCH_QUEUE_CONCURRENT 类型的并发队列,所以任务1和任务2顺序是不定的
2. 任务3使用了 dispatch_barrier_async 栅栏函数来创建任务,它有个特点,就是会将前后任
务进行隔离,任务1和任务2必须都执行完了才会执行任务3,任务4必须等任务3执行完了才能执行
3. 所以任务3在任务1和任务2之后,但是在任务4之前
示例5
- (void)asynDemo1
{
dispatch_queue_t queue = dispatch_queue_create("com.demo", DISPATCH_QUEUE_CONCURRENT);
NSLog(@"1");
dispatch_async(queue, ^{
NSLog(@"2");
dispatch_async(queue, ^{
NSLog(@"3");
});
NSLog(@"4");
});
NSLog(@"5");
}
复制代码
结果:
15243
分析:
- 按执行顺序,先打印1
2. dispatch_async创建了异步线程,在后台等待,继续往下执行打印5
3. 异步任务被调用后,先打印2,然后创建一个新异步任务等待调度执行,继续往下执行打印4
4. 最后打印3
示例6
- (void)syncdemo2 {
dispatch_queue_t queue = dispatch_queue_create("com.demo", DISPATCH_QUEUE_CONCURRENT);
NSLog(@"1");
dispatch_async(queue, ^{
NSLog(@"2");
dispatch_sync(queue, ^{ NSLog(@"3"); });
NSLog(@"4");
});
NSLog(@"5");
}
复制代码
结果:
15234
分析:
- 按顺序执行,先打印 1
2. dispatch_async 创建了异步任务,在后台等待执行,继续往下执行打印 5
3. 异步任务被调用后,先打印 2
4. 创建一个同步任务堵塞线程,等待同步任务执行完毕后才能继续往下执行,所以打印 3
5. 最后打印 4
示例7
- (void)deadLockTest
{
dispatch_queue_t queue = dispatch_queue_create("com.demo", NULL);
NSLog(@"1");
dispatch_async(queue, ^{
NSLog(@"2");
dispatch_sync(queue, ^{
NSLog(@"3");
});
NSLog(@"4");
});
NSLog(@"5");
}
复制代码
结果:
152崩溃
分析:
- 按顺序执行,先打印1
2. dispatch_async创建了异步任务,在后台等待执行,继续往下执行打印5
3. 异步任务被调用,先打印2
4. 创建一个同步任务3,由于queue是串行队列,任务3需要等待异步任务执行完毕后才能执行,但是异步任务 又需要等待任务3执行完毕后才能继续往下执行打印4,你依赖我,我依赖你,这里就造成了死锁,最终导致 EXC_BAD_INSTRUCTION 异常错误