Thus far, we have only talked about single-threaded apps. A single-threaded app only uses one core and is executing only one function at a time. Multithreaded apps can execute multiple functions simultaneously on different cores.
In Chapter 11, you created a singleton like this:
+ (instancetype)sharedStore { static BNRImageStore *sharedStore = nil; if (!sharedStore) { sharedStore = [[self alloc] initPrivate]; } return sharedStore; } // No one should call init - (instancetype)init { @throw [NSException exceptionWithName:@"Singleton" reason:@"Use +[BNRImageStore sharedStore]" userInfo:nil]; return nil; } - (instancetype)initPrivate { self = [super init]; if (self) { _dictionary = [[NSMutableDictionary alloc] init]; } return self; }
This singleton technique is sufficient in a single-threaded app. However, if your app is multithreaded, you could end up creating two instances of BNRImageStore. Or, you might return an instance for use before it gets properly initialized.
You can create a singleton that is thread-safe by using the function dispatch_once to ensure that code is run exactly once.
Open BNRImageStore.m and alter your sharedStore method to make BNRImageStore a thread-safe singleton:
+ (instancetype)sharedStore { static BNRImageStore *sharedStore = nil; if (!sharedStore) { sharedStore = [[self alloc] initPrivate]; } static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ sharedStore = [[self alloc] initPrivate]; }); return sharedStore; }
Build and run it. You should see no change in behavior, but your sharedStore method is now thread-safe.