MST

星途 面试题库

面试题:Objective-C使用GCD实现线程安全的单例模式

在Objective-C中,使用GCD来实现一个线程安全的单例模式,并解释为什么这种实现方式能够保证线程安全,以及在多线程环境下的性能优势。
48.8万 热度难度
编程语言Objective-C

知识考点

AI 面试

面试题答案

一键面试

代码实现

#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

线程安全原因

  1. dispatch_once 机制dispatch_once 是GCD提供的一种保证代码块只被执行一次的机制。它使用一个 dispatch_once_t 类型的变量作为标记,在多线程环境下,无论有多少个线程同时调用 sharedInstance 方法,dispatch_once 中的代码块只会被执行一次,从而保证了单例实例只会被创建一次。
  2. 内部实现原理dispatch_once 内部通过一个原子操作来检测标记变量的状态。如果标记变量表明代码块还未执行,就会锁定执行代码块的区域,执行完代码块后再解锁并更新标记变量。这种机制确保了即使多个线程同时尝试创建单例,也只有一个线程能够成功创建,其他线程会等待并最终获取到已经创建好的单例实例。

多线程环境下的性能优势

  1. 延迟初始化:只有在第一次调用 sharedInstance 方法时才会创建单例实例,而不是在程序启动时就创建,这在一定程度上优化了内存使用和启动时间。
  2. 高效的线程同步:相比于传统的使用锁(如 @synchronized)来实现线程安全的单例模式,dispatch_once 使用的是基于队列的机制,其内部实现针对多核处理器进行了优化,性能更高。在高并发环境下,锁机制可能会导致线程争用,从而降低性能,而 dispatch_once 能够避免这种情况,因为它只在第一次初始化时进行同步操作,后续调用直接返回已创建的实例,大大提高了访问效率。