代码实现
#import <Foundation/Foundation.h>
@interface Singleton : NSObject
@property (nonatomic, strong, readonly) NSString *data;
@property (nonatomic, assign, readonly) NSInteger number;
+ (instancetype)sharedInstance;
@end
@implementation Singleton
static Singleton *sharedInstance = nil;
static dispatch_once_t onceToken;
+ (instancetype)sharedInstance {
dispatch_once(&onceToken, ^{
sharedInstance = [[self alloc] init];
});
return sharedInstance;
}
- (instancetype)init {
self = [super init];
if (self) {
_data = @"Initial Data";
_number = 0;
}
return self;
}
@end
线程安全原因
dispatch_once
机制:dispatch_once
是GCD提供的一种保证代码块只被执行一次的机制。它使用一个 dispatch_once_t
类型的变量作为标记,在多线程环境下,无论有多少个线程同时调用 sharedInstance
方法,dispatch_once
中的代码块只会被执行一次,从而保证了单例实例只会被创建一次。
- 内部实现原理:
dispatch_once
内部通过一个原子操作来检测标记变量的状态。如果标记变量表明代码块还未执行,就会锁定执行代码块的区域,执行完代码块后再解锁并更新标记变量。这种机制确保了即使多个线程同时尝试创建单例,也只有一个线程能够成功创建,其他线程会等待并最终获取到已经创建好的单例实例。
多线程环境下的性能优势
- 延迟初始化:只有在第一次调用
sharedInstance
方法时才会创建单例实例,而不是在程序启动时就创建,这在一定程度上优化了内存使用和启动时间。
- 高效的线程同步:相比于传统的使用锁(如
@synchronized
)来实现线程安全的单例模式,dispatch_once
使用的是基于队列的机制,其内部实现针对多核处理器进行了优化,性能更高。在高并发环境下,锁机制可能会导致线程争用,从而降低性能,而 dispatch_once
能够避免这种情况,因为它只在第一次初始化时进行同步操作,后续调用直接返回已创建的实例,大大提高了访问效率。