MST

星途 面试题库

面试题:Objective-C单例模式下如何确保线程安全

在Objective-C的单例模式中,当涉及多线程操作时,可能会出现哪些线程安全问题?请描述至少两种确保单例线程安全的方法及其原理,并给出相应代码示例。
24.9万 热度难度
编程语言Objective-C

知识考点

AI 面试

面试题答案

一键面试

可能出现的线程安全问题

  1. 多次实例化:在多线程环境下,如果没有适当的同步机制,多个线程可能同时判断单例实例为 nil,进而各自创建一个实例,导致单例不再是唯一实例。
  2. 数据竞争:当单例对象的属性或内部数据被多个线程同时访问和修改时,可能会出现数据不一致的情况。

确保单例线程安全的方法及其原理

1. 使用 dispatch_once

  • 原理dispatch_once 是基于 GCD(Grand Central Dispatch)的函数,它会保证代码块只被执行一次,无论有多少线程同时调用。它内部使用了一个静态变量来记录代码块是否已经执行过,并且通过底层的原子操作来确保线程安全。
  • 代码示例
#import <Foundation/Foundation.h>

@interface Singleton : NSObject

@property (nonatomic, strong, readonly) NSString *name;
+ (instancetype)sharedInstance;

@end

@implementation Singleton
static Singleton *sharedInstance = nil;

+ (instancetype)sharedInstance {
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        sharedInstance = [[self alloc] init];
        sharedInstance.name = @"Singleton Object";
    });
    return sharedInstance;
}

@end

2. 使用 synchronized 关键字

  • 原理synchronized 会为传入的对象(通常是类对象或单例实例本身)创建一个互斥锁。当一个线程进入 synchronized 代码块时,会获取锁,其他线程必须等待锁被释放才能进入。这样就保证了同一时间只有一个线程能执行创建单例实例的代码。
  • 代码示例
#import <Foundation/Foundation.h>

@interface Singleton : NSObject

@property (nonatomic, strong, readonly) NSString *name;
+ (instancetype)sharedInstance;

@end

@implementation Singleton
static Singleton *sharedInstance = nil;

+ (instancetype)sharedInstance {
    @synchronized(self) {
        if (sharedInstance == nil) {
            sharedInstance = [[self alloc] init];
            sharedInstance.name = @"Singleton Object";
        }
    }
    return sharedInstance;
}

@end