扬庆の博客

死锁

字数统计: 526阅读时长: 2 min
2022/03/23 Share

多线程——死锁

死锁,就是队列引起的循环等待。

  1. 比较常见的例子: 主队列同步

任务添加到主队列(队列: 执行任务的等待的队列), 同步执行,即需要立即执行,(同步: 会造成线程堵塞) , 添加到主队列也就意味着当前任务执行完成才能执行下一个任务(添加到主队列的这个任务);

就会导致当前任务等待刚才添加到主队列的任务执行完才会执行, 而主队列下当前执行的任务又是遵循FIFO先进先出原则,添加到主队列的任务又需要等待当前任务执行完才会继续执行, 就造成了互相等待, 死锁.

看下面代码:

viewDidLoad当前任务被 NSLog(@"deal lock");这个任务块给阻塞了,FIFO原则又需要 viewDidLoad方法内的任务执行完才能继续执行下一个任务,两则互相等待, 照成死锁。

1
2
3
4
5
6
7
-(void)viewDidLoad {
[super viewDidLoad];

dispatch_sync(dispatch_get_main_queue(), ^{
NSLog(@"deal lock");
});
}

同步任务,会阻塞当前线程。

再看一个死锁的例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 创建一个串行队列 名称“test”
dispatch_queue_t serialQueue = dispatch_queue_create("test", DISPATCH_QUEUE_SERIAL);

/* 往序列里添加两个任务 */
// 任务A
distch_async(serialQueue, ^{

// 任务B
dispatch_sync(serialQueue, ^{
NSLog(@"deal lock");
});

});

为什么会死锁?

串行队列FIFO原则,任务A执行完再执行任务B, 任务B在同一个串行队列中, 又因为是同步执行, (阻塞了当前线程), 任务A和任务B互相等待, 造成了死锁。

解决办法
里面的任务B改成异步,或者将 serialQueue 换成其他串行或并行队列,都可以解决。 注意⚠️: 同步执行,同一个串行队列。这两个因素打破其中一个都行。

1
2
3
4
5
6
7
8
9
10
11
dispatch_queue_t serialQueue = dispatch_queue_create("test", DISPATCH_QUEUE_SERIAL);
dispatch_queue_t serialQueue2 = dispatch_queue_create("test", DISPATCH_QUEUE_SERIAL);

dispatch_async(serialQueue, ^{

dispatch_sync(serialQueue2, ^{
NSLog(@"deal lock");
});

});

不会造成死锁, 不再一个队列里面。在一个线程中。

CATALOG
  1. 1. 多线程——死锁