30 lines of code to demonstrate the dispatch [once deadlock]

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

Keywords: xcode

Added by lisa71283 on Thu, 02 Jan 2020 14:24:26 +0200