我遇到了一个与iOS中的队列死锁相关的非常有趣的问题。有什么方法可以避免这种情况吗?
考虑一下:
以下是此示例代码。
由于主队列正在等待opQueue完成任务#3,并且opQueue正在等待主队列完成任务#2,因此存在死锁。
#import "ViewController.h"
@interface ViewController ()
@property(nonatomic,strong) dispatch_queue_t opQueue;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
dispatch_queue_t queue = dispatch_queue_create("com.tarun.sqqueue",
DISPATCH_QUEUE_SERIAL);
self.opQueue = queue;
[self performOperations];
}
/// 1. Dispatch on serial queue async.
/// 2. This async task on serial queue dispatchs some task onto
/// main queue sync.
/// 3. Main queue dispatched some task onto serial queue sync.
/// 4. Result - DeadLock
- (void)performOperations {
/// task#1: Dispatch task on the serial Queue Asynchronously.
/// So this is not blocking.
dispatch_async(self.opQueue, ^{
for (int i = 1; i<=100; i++) {
NSLog(@"%d. Async on Serial Queue from Main Queue.",i);
}
/// task#2: Dispatching task on main queue synchronously from serial
/// queue.So this queue will wait till main queue executes this task.(Blocking)
dispatch_sync(dispatch_get_main_queue(), ^{
for (int i = 1; i<=100; i++) {
NSLog(@"%d. Sync on main queue from Serial Queue.",i);
}
});
});
/// task#3: Dispatching task on swrial queue synchronously from main
/// queue.So main queue will wait till serial queue executes this task. (Blocking)
dispatch_sync(self.opQueue, ^{
for (int i = 1; i<=100; i++) {
NSLog(@"%d. Sync on Serial Queue From Main Queue.",i);
}
});
/// Since self.opQueue is a serial queue, task#3 will not start till task#1 completes.
/// Since task#1 is calling main queue sync,
/// so it will never complete till main queue completes task#2.
/// Since main queue is waiting for opQueue to finish task#3, and opQueue is waiting for main queue to finish task#2 there is a deadlock.
NSLog(@"Back to main queue");
}
@end
答案 0 :(得分:1)
来自Apple
重要提示:您永远不应该调用dispatch_sync或dispatch_sync_f 从您在同一队列中执行的任务中运行 计划传递给函数。这对于特别重要 串行队列,保证死锁,但也应该是 避免并发队列。
保证死锁。避免这种情况的唯一方法是不以这种方式实现它。