死锁: 是指两个或两个以上的进程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去。
发生死锁的情况 一般是两个对象的锁相互等待造成的。
那么为什么会产生死锁呢?有3个原因:第一,因为系统资源不足;第二,进程运行推进的顺序不合适;第三,资源分配不当。
产生死锁的条件有四个:
l 互斥条件:所谓互斥就是进程在某一时间内独占资源。
l 请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放。
l 不剥夺条件:进程已获得资源,在末使用完之前,不能强行剥夺。
l 循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。
死锁通常是一个线程锁定了一个资源A,而又想去锁定资源B;在另一个线程中,锁定了资源B,而又想去锁定资源A以完成自身的操作,两个线程都想得到对方的资源,而不愿释放自己的资源,造成两个线程都在相互等待,造成了无法执行的情况。
避免死锁的一个通用的经验法则是:当几个线程都要访问共享资源A、B、C时,保证使每个线程都按照同样的顺序去访问它们,比如都先访问A,在访问B和C
代码分析:
- (void)viewDidLoad {
//dispatch_sync(dispatch_get_main_queue(), ^{
//NSLog(@3);
//死锁原因
//1:dispatch_sync在等待block语句执行完成,而block语句需要在主线程里执行,所以dispatch_sync如果在主线程调用就会造成死锁
//2:dispatch_sync是同步的,本身就会阻塞当前线程,也即主线程。而又往主线程里塞进去一个block,所以就会发生死锁。
//});
//dispatch_async(dispatch_get_global_queue(), ^{
//async 在主线程中 创建了一个异步线程 加入 全局并发队列,async 不会等待block 执行完成,立即返回
NSLog(@2);//不会造成死锁;
});
}
分析这段代码:view DidLoad 在主线程中,也即dispatch_get_main_queue()中,执行到sync时向dispatch_get_main_queue()插入同步thread,sync会等到后面的block执行完成才返回。sync又在主队列里面,是个串行队列,sync是后面才加入的,前面一个是主线程,所以sync想执行block必须等待前一个主线程执行完成,而主线程却
在等待sync返回,去执行后续工作,从而造成死锁。
2:
dispatch_sync 和 dispatch_async 区别:
dispatch_async(queue,block) async 异步队列,dispatch_async
函数会立即返回, block会在后台异步执行。
dispatch_sync(queue,block) sync 同步队列,dispatch_sync
函数不会立即返回,即阻塞当前线程,等待 block同步执行完成。
接下来是同步与异步线程的创建:
1
2
3
|
dispatch_sync
(
.
.
.
,
^
(
block
)
)
// 同步线程
dispatch_async
(
.
.
.
,
^
(
block
)
)
// 异步线程
|
案例与分析
假设你已经基本了解了上面提到的知识,接下来进入案例讲解阶段。
案例一:
1
2
3
4
5
6
|
NSLog
(
@"1"
)
;
// 任务1
dispatch_sync
(
dispatch_get_main_queue
(
)
,
^
{
|