0%

GCD什么情况下会死锁?

A serial dispatch queue runs only one task at a time, waiting until that task is complete before dequeuing and starting a new one. By contrast, a concurrent dispatch queue starts as many tasks as it can without waiting for already started tasks to finish.

串行队列-同步-同步

运行结果:死锁。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/**
条件:串行队列,同步执行,同步执行。
结果:死锁。
*/
- (void) testMethod2 {
dispatch_queue_t queue = dispatch_queue_create("com.serial", DISPATCH_QUEUE_SERIAL);
NSLog(@"11");
dispatch_sync(queue, ^{
NSLog(@"22");
dispatch_sync(queue, ^{
NSLog(@"33");
});
NSLog(@"44");
});
NSLog(@"55");
}

运行截图:

串行队列-同步-异步

运行结果:不死锁,同步操作在主线程中执行,异步操作在子线程执行。为什么第一个同步操作没有死锁,因为第一个同步操作在“com.serial”这个队列里,而testMethod10在主队列里,虽然是同步操作,但是二者不属于同一个队列,不会互相阻塞。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/**
条件:串行队列,同步执行,异步执行。
结果:死锁。
*/
- (void) testMethod10 {
dispatch_queue_t queue = dispatch_queue_create("com.serial", DISPATCH_QUEUE_SERIAL);
NSLog(@"11, %@", [NSThread currentThread]);
dispatch_sync(queue, ^{
NSLog(@"22, %@", [NSThread currentThread]);
dispatch_async(queue, ^{
NSLog(@"33, %@", [NSThread currentThread]);
});
NSLog(@"44, %@", [NSThread currentThread]);
});
NSLog(@"55, %@", [NSThread currentThread]);
}

运行截图:

串行队列-异步-同步

运行结果:死锁。打印“22”、“44”的操作已经在串行队列上执行了,此时要求插入打印“33”的操作,这个同步操作造成“com.serial”串行队列死锁。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/**
条件:串行队列,异步执行,同步执行。
结果:死锁。
*/
- (void) testMethod5 {
dispatch_queue_t queue = dispatch_queue_create("com.serial", DISPATCH_QUEUE_SERIAL);
NSLog(@"11, %@", [NSThread currentThread]);
dispatch_async(queue, ^{
NSLog(@"22, %@", [NSThread currentThread]);
dispatch_sync(queue, ^{
NSLog(@"33, %@", [NSThread currentThread]);
});
NSLog(@"44, %@", [NSThread currentThread]);
});
NSLog(@"55, %@", [NSThread currentThread]);
}

运行截图:

串行队列-异步-异步

运行结果:不死锁。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/**
条件:串行队列,异步执行,异步执行。
结果:不死锁。
线程:创建了一个线程。
*/
- (void) testMethod8 {
dispatch_queue_t queue = dispatch_queue_create("com.serial", DISPATCH_QUEUE_SERIAL);
NSLog(@"11, %@", [NSThread currentThread]);
dispatch_async(queue, ^{
NSLog(@"22, %@", [NSThread currentThread]);
dispatch_async(queue, ^{
NSLog(@"33, %@", [NSThread currentThread]);
});
NSLog(@"44, %@", [NSThread currentThread]);
});
NSLog(@"55, %@", [NSThread currentThread]);
}

运行截图:

并发队列-同步-同步

运行结果:不死锁。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/**
条件:并发队列,同步执行,同步执行。
结果:不死锁。
*/
- (void) testMethod3 {
dispatch_queue_t queue = dispatch_queue_create("com.serial.11", DISPATCH_QUEUE_CONCURRENT);
NSLog(@"11, %@", [NSThread currentThread]);
dispatch_sync(queue, ^{
NSLog(@"22, %@", [NSThread currentThread]);
dispatch_sync(queue, ^{
NSLog(@"33, %@", [NSThread currentThread]);
});
NSLog(@"44, %@", [NSThread currentThread]);
});
NSLog(@"55, %@", [NSThread currentThread]);
}

运行截图:

并发队列-同步-异步

运行结果:不死锁。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/**
条件:并发队列,同步执行,异步执行。
结果:不死锁。
*/
- (void) testMethod11 {
dispatch_queue_t queue = dispatch_queue_create("com.serial.11", DISPATCH_QUEUE_CONCURRENT);
NSLog(@"11, %@", [NSThread currentThread]);
dispatch_sync(queue, ^{
NSLog(@"22, %@", [NSThread currentThread]);
dispatch_async(queue, ^{
NSLog(@"33, %@", [NSThread currentThread]);
});
NSLog(@"44, %@", [NSThread currentThread]);
});
NSLog(@"55, %@", [NSThread currentThread]);
}

运行截图:

并发队列-异步-同步

运行结果:不死锁。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/**
条件:并发队列,异步执行,同步执行。
结果:不死锁。
*/
- (void) testMethod6 {
dispatch_queue_t queue = dispatch_queue_create("com.serial.11", DISPATCH_QUEUE_CONCURRENT);
NSLog(@"11, %@", [NSThread currentThread]);
dispatch_async(queue, ^{
NSLog(@"22, %@", [NSThread currentThread]);
dispatch_sync(queue, ^{
NSLog(@"33, %@", [NSThread currentThread]);
});
NSLog(@"44, %@", [NSThread currentThread]);
});
NSLog(@"55, %@", [NSThread currentThread]);
}

运行截图:

并发队列-异步-异步

运行结果:不死锁。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/**
条件:并发队列,异步执行,异步执行。
结果:不死锁。
线程:创建了一个线程。
*/
- (void) testMethod9 {
dispatch_queue_t queue = dispatch_queue_create("com.serial.11", DISPATCH_QUEUE_CONCURRENT);
NSLog(@"11, %@", [NSThread currentThread]);
dispatch_async(queue, ^{
NSLog(@"22, %@", [NSThread currentThread]);
dispatch_async(queue, ^{
NSLog(@"33, %@", [NSThread currentThread]);
});
NSLog(@"44, %@", [NSThread currentThread]);
});
NSLog(@"55, %@", [NSThread currentThread]);
}

运行截图:

主队列-同步-同步

运行结果:死锁。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/**
条件:主队列,同步执行,同步执行。
结果:死锁。
*/
- (void) testMethod1 {
dispatch_queue_t queue = dispatch_get_main_queue();
NSLog(@"11, %@", [NSThread currentThread]);
dispatch_sync(queue, ^{
NSLog(@"22, %@", [NSThread currentThread]);
dispatch_sync(queue, ^{
NSLog(@"33, %@", [NSThread currentThread]);
});
NSLog(@"44, %@", [NSThread currentThread]);
});
NSLog(@"55, %@", [NSThread currentThread]);
}

运行截图:

主队列-同步-异步

运行结果:死锁。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/**
条件:主队列,同步执行,异步执行。
结果:死锁。
*/
- (void) testMethod12 {
dispatch_queue_t queue = dispatch_get_main_queue();
NSLog(@"11, %@", [NSThread currentThread]);
dispatch_sync(queue, ^{
NSLog(@"22, %@", [NSThread currentThread]);
dispatch_async(queue, ^{
NSLog(@"33, %@", [NSThread currentThread]);
});
NSLog(@"44, %@", [NSThread currentThread]);
});
NSLog(@"55, %@", [NSThread currentThread]);
}

运行截图:

主队列-异步-同步

运行结果:死锁。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/**
条件:主队列,异步执行,同步执行。
结果:死锁。
*/
- (void) testMethod4 {
dispatch_queue_t queue = dispatch_get_main_queue();
NSLog(@"11, %@", [NSThread currentThread]);
dispatch_async(queue, ^{
NSLog(@"22, %@", [NSThread currentThread]);
dispatch_sync(queue, ^{
NSLog(@"33, %@", [NSThread currentThread]);
});
NSLog(@"44, %@", [NSThread currentThread]);
});
NSLog(@"55, %@", [NSThread currentThread]);
}

运行截图:

主队列-异步-异步

运行结果:不死锁。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/**
条件:主队列,异步执行,异步执行。
结果:不死锁。
线程:主线程执行。
*/
- (void) testMethod7 {
dispatch_queue_t queue = dispatch_get_main_queue();
NSLog(@"11, %@", [NSThread currentThread]);
dispatch_async(queue, ^{
NSLog(@"22, %@", [NSThread currentThread]);
dispatch_async(queue, ^{
NSLog(@"33, %@", [NSThread currentThread]);
});
NSLog(@"44, %@", [NSThread currentThread]);
});
NSLog(@"55, %@", [NSThread currentThread]);
}

运行截图:

总结:在并发队列上,无论是同步还是异步都不会发生死锁;主队列上只有异步执行的时候才不会发生死锁;串行队列是否发生死锁需要具体分析。

参考链接

官方文档