本文不深层次讨论同步、异步。不深层次讨论串行、并行。本文只说什么是死锁?如何造出来死锁?常见的几种死锁?怎么解决死锁?
死锁:程序在循环体中一直打转出不来了。
怎么造出来死锁:调用同步的线程如果和target线程是同一个线程就会出现死锁。
常见的两种死锁。
1. 主线程调用主线程。备注:最容易忽视出现死锁的方式。
2. 同步串行队列嵌套自己。备注:一般不会出现。
不说废话了。直接上代码。
(void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
// 死锁场景一 主线程调用主线程
// [self diedLockCase1];
// 死锁场景一的解决方式
// [self asyncReleaseLockCase1];
// [self newThreadReleaseCase1];
//死锁场景二 同步串行队列嵌套
// [self diedLockCase2];
//死锁场景二的解决方式
// [self asyncReleaseCase2];
// [self syncdifthredReleaseCase2];
[self asyncdifthredReleaseCase2];
}
/**- 从控制台输出可以看出,任务2和任务3没有执行,此时已经死锁了。
- 因为dispatch_sync是同步的,本身就会阻塞当前线程,此刻阻塞了主线程。
- 而当前block又在等待主线程执行完毕,从而形成了主线程等待主线程,自己等自己的情况,形成了死锁。
*/
-(void)diedLockCase1{
NSLog(@”1”);
dispatch_sync(dispatch_get_main_queue(), ^{
NSLog(@”2”);
});
NSLog(@”3”);
}
/**- 解决方式一 异步
*/
-(void)asyncReleaseLockCase1{
NSLog(@”1”);
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(@”2”);
});
NSLog(@”3”);
}
/**
* 解决方式一 子线程
* 如果 Block 中刷新 UI 的操作,则不能放在主线程中执行。会 Crash
*/
-(void)newThreadReleaseCase1{
NSLog(@"1");
dispatch_sync(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSLog(@"2");
});
NSLog(@"3");
}
/**
*Calls to dispatch_sync() targeting the current queue will result
* in dead-lock.
* 调用 同步的线程如果和target线程是同一个线程就有可能会出现dead-lock。
* 输出结果是 1 2
*/
-(void)diedLockCase2{
dispatch_queue_t aSerialDispatchQueue = dispatch_queue_create("com.kongleifeng.queue", DISPATCH_QUEUE_SERIAL);
NSLog(@"1");
dispatch_sync(aSerialDispatchQueue, ^{
NSLog(@"2");
dispatch_sync(aSerialDispatchQueue, ^{
NSLog(@"3");
});
NSLog(@"4");
});
NSLog(@"5");
}
/**
* 输出的顺序 1 2 4 其中 3 5 顺序不定
*/
-(void)asyncReleaseCase2{
dispatch_queue_t aSerialDispatchQueue = dispatch_queue_create("com.kongleifeng.queue", DISPATCH_QUEUE_SERIAL);
NSLog(@"1");
dispatch_sync(aSerialDispatchQueue, ^{
NSLog(@"2");
dispatch_async(aSerialDispatchQueue, ^{
NSLog(@"3");
});
NSLog(@"4");
});
NSLog(@"5");
// dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 5*NSEC_PER_SEC), dispatch_get_main_queue(), ^{
//
// });
// for (int i = 0 ; i < 100; i++) {
// NSLog(@”a+i=%d”,i);
// }
}
/**
* 嵌套时 更换不同的线程
*/
-(void)syncdifthredReleaseCase2{
dispatch_queue_t aSerialDispatchQueue = dispatch_queue_create("com.kongleifeng.queue", DISPATCH_QUEUE_SERIAL);
dispatch_queue_t aSerialDispatchQueue1 = dispatch_queue_create("com.kongleifeng.queue", DISPATCH_QUEUE_SERIAL);
NSLog(@"1");
dispatch_sync(aSerialDispatchQueue, ^{
NSLog(@"2");
dispatch_sync(aSerialDispatchQueue1, ^{
NSLog(@"3");
});
NSLog(@"4");
});
NSLog(@"5");
}
/**
* 可以输出 1 2 3 4 5 但是可以确定的顺序 1 最前面。2 在 3 4 的前面。2 与 5 之前的顺序不定。
*/
-(void)asyncdifthredReleaseCase2{
dispatch_queue_t aSerialDispatchQueue = dispatch_queue_create("com.kongleifeng.queue", DISPATCH_QUEUE_SERIAL);
NSLog(@"1");
dispatch_async(aSerialDispatchQueue, ^{
NSLog(@"2");
dispatch_async(aSerialDispatchQueue, ^{
NSLog(@"3");
});
NSLog(@"4");
});
NSLog(@"5");
}