Example 1
- (void)surpassNum
{
while (self.num < 500) {
dispatch_async(dispatch_get_global_queue(0, 0), ^{
self.num++;
});
}
NSLog(@"num is %d",self.num);
}
复制代码
Result : The print result is >=500
Analysis :
-
When entering the loop for the first time, self.num = 0, and an asynchronous task is created at this time, but this task is not necessarily executed immediately, it will wait for the first-out scheduling, and then it will enter the next loop. Since the task is executed, So self.num++ is not executed, so in the second loop, self.num is still equal to 0, and a new asynchronous task will be created at this time, and so on, at least 500 asynchronous tasks will be common.
-
Since self.num<500 is used as the termination condition in the while loop, only when self.num >=500 can it jump out of the loop and print
-
In the middle of jumping out of the loop to execute printing, there may be multiple asynchronous tasks executed, which is equivalent to self.num++ being executed N times
-
So the print result must be >=500
Extension: If dispatch_async is replaced by dispatch_sync synchronization task, the print result must be 500, because the synchronization task will block the thread, and the next loop cannot be executed until self.num++ is executed.
Example 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);
}
复制代码
Result : Print result 0-999 Analysis :
-
The for loop is used here, and the temporary variable i is used instead of self.num for judgment. Self.num has nothing to do with the loop, so only 999 loops are executed here, that is, 999 asynchronous tasks are created.
-
When i== 1000, the for loop terminates. Although 999 asynchronous tasks are created at this time, are these tasks completed? Obviously not, it needs to wait for the thread to schedule; so before printing, how many tasks can be executed? , this is uncertain, maybe a task has not been executed, maybe all executed, then the print result may be 0-999
-
Although it is theoretically 0-999, the print result will still be close to 999
Example 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");
});
}
复制代码
Q: What is the possible reason for the above printout?
- A: 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 异常错误