30 lines of code to demonstrate the dispatch [once deadlock]
If you encounter a crash like the following, you may also encounter a dispatch [once] deadlock.
Thread 0 Crashed:
0 libsystem_kernel.dylib 0x00000001917718e8 __ulock_wait + 8
1 libdispatch.dylib 0x00000001916419d0 _dispatch_unfair_lock_wait + 48
2 libdispatch.dylib 0x0000000191641b6c _dispatch_gate_wait_slow + 88
3 libdispatch.dylib 0x000000019162f710 dispatch_once_f + 124
4 Demo 0x00000001004073b8 +[MyObject sharedUserInstance]
Don't worry about asking me how to solve it. Run the following code in xcode and analyze it for yourself to know how to solve it.
30Line code demonstrationdispatch_oncedeadlock
96 giveme5 follow
2017.05.31 20:25* Word number 143 Read 45comment 0like 0
//If you have a breakdown like this, you may have one toodispatch_onceDeadlock.
Thread 0 Crashed:
0 libsystem_kernel.dylib 0x00000001917718e8 __ulock_wait + 8
1 libdispatch.dylib 0x00000001916419d0 _dispatch_unfair_lock_wait + 48
2 libdispatch.dylib 0x0000000191641b6c _dispatch_gate_wait_slow + 88
3 libdispatch.dylib 0x000000019162f710 dispatch_once_f + 124
4 Demo 0x00000001004073b8 +[MyObject sharedUserInstance]
//Don't worry about asking me how to solve it. Run the following code in xcode and analyze it for yourself to know how to solve it.
@interface MyObject : NSObject
+ (instancetype)sharedInstance;
@end
@implementation MyObject
+ (instancetype)sharedInstance{
static id sharedInstance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedInstance = [[self alloc] init];
});
return sharedInstance;
}
- (instancetype)init{
self = [super init];
if (self) {
[NSThread sleepForTimeInterval:2];//Wait for 2 seconds.
dispatch_sync(dispatch_get_main_queue(), ^{
NSLog(@"Never print because it's deadlocked");
});
}
return self;
}
@end
@implementation ViewController
- (IBAction)clicked:(id)sender {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[MyObject sharedInstance];
});
[MyObject sharedInstance];
}
@end
The analysis is as follows:
0 seconds. Click the button to execute dispatch once in the global queue
0.1 seconds. Main queue is blocked, waiting to get the once token
2 seconds. Global queue ends sleep, executes dispatch sync, blocks and waits for main queue. This deadlock occurs.
Reference resources:
Deadlock caused by dispatch [once] - analysis, solution and automatic detection