Reputation: 871
I have come across a very interesting problem related to queue dead lock in iOS. Any way to avoid this?
Consider this:
Below is the sample code for this.
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.
#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
Upvotes: 1
Views: 397
Reputation: 5241
From Apple
Important: You should never call the dispatch_sync or dispatch_sync_f function from a task that is executing in the same queue that you are planning to pass to the function. This is particularly important for serial queues, which are guaranteed to deadlock, but should also be avoided for concurrent queues.
Its a guaranteed dead lock. The only way to avoid this is to not implement it this way.
Upvotes: 1