Last active
August 29, 2015 14:05
-
-
Save hirad/0e24fc3a91be87317ab1 to your computer and use it in GitHub Desktop.
An empty app to demonstrate race conditions in Objective-C and how to fix it with GCD.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@interface LHLAppDelegate : UIResponder <UIApplicationDelegate> | |
@property (strong, nonatomic) UIWindow *window; | |
@property (strong, nonatomic) NSNumber* counter; // will making this 'atomic' solve our problem? | |
@property (strong, nonatomic) dispatch_queue_t isolationQueue; | |
@property (strong, nonatomic) NSRecursiveLock* lock; | |
@end | |
@implementation LHLAppDelegate | |
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions | |
{ | |
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; | |
// Override point for customization after application launch. | |
self.window.backgroundColor = [UIColor whiteColor]; | |
[self.window setRootViewController:[UIViewController new]]; | |
[self.window makeKeyAndVisible]; | |
self.isolationQueue = dispatch_queue_create("com.Lighthouse-Labs.isolationQueue", 0); | |
self.lock = [NSRecursiveLock new]; | |
self.counter = @0; | |
// let's get the default concurrent queue | |
dispatch_queue_t q = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); | |
// let's create 4 blocks, each of which will increment our counter 1000 times | |
void (^asyncBlock)() = ^{ | |
for (int i = 0 ; i < 1000; i++) { | |
[self incrementCounter]; | |
} | |
NSLog(@"Finished increments. Current count: %ld", | |
(long)[self.counter integerValue]); | |
}; | |
dispatch_async(q, asyncBlock); | |
dispatch_async(q, asyncBlock); | |
dispatch_async(q, asyncBlock); | |
dispatch_async(q, asyncBlock); | |
return YES; | |
} | |
-(void)incrementCounter | |
{ | |
[self incrementCounterWithIsolationQueue]; | |
} | |
-(void)incrementCounterUnsafe | |
{ | |
self.counter = @([self.counter integerValue] + 1); | |
} | |
-(void)incrementCounterWithIsolationQueue | |
{ | |
dispatch_async(self.isolationQueue, ^{ | |
self.counter = @([self.counter integerValue] + 1); | |
}); | |
} | |
-(void)incrementCounterWithLock | |
{ | |
[self.lock lock]; | |
self.counter = @([self.counter integerValue] + 1); | |
[self.lock unlock]; | |
} | |
-(void)incrementCounterWithSynchronized | |
{ | |
@synchronized(self) { | |
self.counter = @([self.counter integerValue] + 1); | |
} | |
} | |
@end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment