GCD的同异步、串并行以及队列死锁的问题
来源:互联网 发布:黑色沙漠男法捏脸数据 编辑:程序博客网 时间:2024/06/16 01:53
概念解释:
同步和异步决定了要不要开启新的线程
同步:在当前线程中执行任务,不具备开启新线程的能力
异步:在新的线程中执行任务,具备开启新线程的能力
并发和串行决定了任务的执行方式
并发:多个任务并发(同时)执行
串行:一个任务执行完毕后,再执行下一个任务
通过GCD可获得的三种队列
1.全局并发队列
2.主队列(跟主线程相关联的队列)
3.自定义队列
三种队列通过同步、异步方式,实验下6种方式:
1.全局并发队列,同步方式
- (void)count{ for (int i = 0; i < 5; i++) { NSLog(@"num:%d",i); }}- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{ //获取全局队列 dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); dispatch_sync(queue, ^{ NSLog(@"下载图片1---%@", [NSThread currentThread]); [self count]; }); dispatch_sync(queue, ^{ NSLog(@"下载图片2---%@", [NSThread currentThread]); [self count]; });}
运行结果:
number = 1表示当前是主线程,因为是dispatch_sync同步方式往全局队列中添加的任务,可见并没有开启新的线程。
2.全局并发队列,异步方式
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{ dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); dispatch_async(queue, ^{ NSLog(@"下载图片3---%@", [NSThread currentThread]); [self count]; }); dispatch_async(queue, ^{ NSLog(@"下载图片4---%@", [NSThread currentThread]); [self count]; });}
运行结果:
可以看到number =4,number = 3,意味着开启了两个子线程去完成任务,观察num:0 num:0 ,交替打印出num的值,可以理解为两个任务同时进行,即并行处理
3.主队列,同步方式
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{ dispatch_queue_t queue = dispatch_get_main_queue(); dispatch_sync(queue, ^{ NSLog(@"下载图片1---%@", [NSThread currentThread]); [self count]; }); dispatch_sync(queue, ^{ NSLog(@"下载图片2---%@", [NSThread currentThread]); [self count]; });}
这里运行,看起来并没有什么反应,也没有什么什么结果在Xcode上打印出来,为什么呢?这里涉及到串行队列中执行串行同步操作造成死锁的问题。
*首先大环境是主队列(主队列本质是串行队列 遵循FIFO),在主队列中,使用同步函数在主队列(相当于在相同的串行队列)末尾加入了任务。主队列 遇到了同步函数,准备继续往下执行程序,但是同步函数这时候也要执行,这意味着程序需要等待同步函数执行完成后才能继续。那么同步函数什么时候执行完成呢?同步函数需要等它自己block中的任务执行结束,而block种的任务什么时候执行结束呢?根据串行队列FIFO原则,要等待主队列中block这个任务前面所有的任务完成,而block任务是在主队列队尾,block前面的任务至少还有一个同步函数dispatch_sync()这个任务,所以block必须等待dispatch_sync()执行完。 那么问题来了,dispatch_sync()等待block执行完,block又在等待dispatch_sync()执行完,互相等待,这就造成死锁了。主要原因是主队列是串行队列。
4.主队列,异步方式
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{ [self count]; dispatch_queue_t queue = dispatch_get_main_queue(); dispatch_async(queue, ^{ NSLog(@"下载图片3---%@", [NSThread currentThread]); [self count]; }); dispatch_async(queue, ^{ NSLog(@"下载图片4---%@", [NSThread currentThread]); [self count]; });}
分析一下:
*异步方式开启,等主线程执行完操作,才处理主队列中的任务
*虽然是异步方式,但是number = 1,并没有开启新的线程
5.自创建串行队列,同步方式
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{ dispatch_queue_t queue = dispatch_queue_create("myqueue", DISPATCH_QUEUE_SERIAL); dispatch_sync(queue, ^{ NSLog(@"下载图片1---%@", [NSThread currentThread]); [self count]; }); dispatch_sync(queue, ^{ NSLog(@"下载图片2---%@", [NSThread currentThread]); [self count]; });}
*同步方式,串行队列,没有开启新线程。
*由于同步函数不具备开启新线程的能力,所以就不列举同步函数执行并发队列的 例子了。
6.自创建并发队列,异步方式
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{ dispatch_queue_t queue = dispatch_queue_create("myqueue", DISPATCH_QUEUE_CONCURRENT); dispatch_sync(queue, ^{ NSLog(@"下载图片1---%@", [NSThread currentThread]); [self count]; }); dispatch_sync(queue, ^{ NSLog(@"下载图片2---%@", [NSThread currentThread]); [self count]; });}
*异步方式,观察number =3,number=4,意味着,开启了两个新的线程处理任务
*num打印的值来看,由于创建的并发队列,所以并行处理。类似例子1中的全局队列,同步方式。
小结
- GCD的同异步、串并行以及队列死锁的问题
- GCD的队列,死锁
- iOS中的GCD(1)---串、并行队列和同、异步添加
- GCD的串行队列和并行队列
- GCD串、并行队列
- GCD使用 串行并行队列 与 同步异步执行的各种组合 及要点分析
- GCD使用 串行并行队列 与 同步异步执行的各种组合 及要点分析
- GCD 的使用 并行串行 队列
- GCD 中串行队列、并行队列、dispatch_sync、dispatch_async的关系
- 关于GCD 队列,同步异步的理解
- 同步队列的死锁问题
- GCD编程中串行、并行、同步、异步的执行顺序
- gcd中同步异步并行串行线程数目的关系
- GCD的死锁
- GCD死锁的理解
- 并发和并行的区别 以及线程的死锁
- GCD 串行队列和并行队列以及dispatch_group
- GCD 队列串行 并行 同步 异步 小例
- codeforces 276D D. Little Girl and Maximum XOR(贪心+dp+数论)
- session的生命周期
- 少年啊,来一发昆特吗(二)——昆特牌的触摸
- Jsp中的九大内置对象和四大作用域
- C++中内存对齐
- GCD的同异步、串并行以及队列死锁的问题
- zookeeper系列:zookeeper使用和原理探究
- 栈的应用之括号的匹配Java语言描述
- EditText组件drawableLeft属性设置的图片和hint设置的文字之间的距离
- AndroidStudio如何使用aar依赖包?
- NGinx负载均衡策略
- 最优二叉搜索树问题
- 腾讯一面:C++的private、public、protected继承的区别
- hduacm 5433 Xiao Ming climbing题解