You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Objective-C对未初始化或重赋值的实例变量用@synchronized是否安全?

你当前的写法既不合法也不安全,无法解决多线程竞态问题,建议改为使用self或生命周期与当前类实例绑定的独立对象作为锁对象。

现有方案的两个核心风险

  • 对未初始化的nil对象加锁无任何效果:Objective-C中@synchronized的参数如果为nil,同步块会直接失去互斥能力,等同于没有加锁。你第一次调用reinitialize方法时,sharedState尚未赋值为有效值,此时加锁完全无法防止其他线程同时操作,竞态问题依然存在。
  • 更换锁对象指针会直接破坏互斥逻辑:@synchronized是对传入的对象实例加锁,而非对指针变量本身加锁。当你在同步块内将sharedState指向新的字典实例后,后续其他线程进入同步块时会拿到新的对象作为锁,和之前正在执行的同步块使用的锁完全无关,无法起到互斥作用。比如线程A持有旧锁正在读写sharedState,线程B调用reinitialize更换了指针后,线程C再进入同步块使用新锁,就会和线程A同时执行操作,直接触发崩溃。

正确实现方案

你可以直接使用self作为锁对象,保证所有操作使用的锁在实例生命周期内不会变化,所有读写sharedState的代码、包括reinitialize都包裹在同一个@synchronized(self)块中即可,示例代码如下:

@interface MyClass: NSObject {
    NSMutableDictionary *sharedState;
}
@end

@implementation MyClass

- (instancetype)init {
    self = [super init];
    if (self) {
        [self reinitialize];
    }
    return self;
}

- (void)reinitialize {
    @synchronized (self) {
        sharedState = [[NSMutableDictionary alloc] init];
    }
}

// 读取操作示例
- (id)getValueForKey:(NSString *)key {
    @synchronized (self) {
        return sharedState[key];
    }
}

// 修改操作示例
- (void)setValue:(id)value forKey:(NSString *)key {
    @synchronized (self) {
        sharedState[key] = value;
    }
}

@end

如果你的类有大量外部同时操作的场景,担心self作为锁会和外部的@synchronized(self)操作产生不必要的互斥,也可以单独声明一个私有锁实例变量,锁的粒度更可控,不会和类外部的锁产生冲突:

@interface MyClass: NSObject {
    NSMutableDictionary *sharedState;
    id _lock;
}
@end

@implementation MyClass

- (instancetype)init {
    self = [super init];
    if (self) {
        _lock = [[NSObject alloc] init];
        [self reinitialize];
    }
    return self;
}

- (void)reinitialize {
    @synchronized (_lock) {
        sharedState = [[NSMutableDictionary alloc] init];
    }
}

// 其余操作都使用@synchronized(_lock)包裹
@end

内容的提问来源于stack exchange,提问作者bdesham

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.06 09:24:04