MST

星途 面试题库

面试题:Objective-C关联对象在多线程环境下的应用及问题处理

在多线程环境中使用Objective-C关联对象,可能会遇到哪些问题?请阐述如何通过合理选择关联策略以及添加同步机制来避免这些问题,并给出相应的代码示例。
48.5万 热度难度
编程语言Objective-C

知识考点

AI 面试

面试题答案

一键面试

可能遇到的问题

  1. 数据竞争:多个线程同时对关联对象进行设置或获取操作,可能导致数据不一致。例如,一个线程正在设置关联对象的值,另一个线程同时获取该值,可能获取到未完全设置好的数据。
  2. 内存管理问题:在多线程环境下,关联对象的内存释放可能会出现问题。如果一个线程释放了关联对象所依赖的内存,而其他线程仍在尝试访问该关联对象,可能导致程序崩溃。

避免问题的方法

  1. 选择合适的关联策略
    • 使用OBJC_ASSOCIATION_RETAIN_NONATOMIC时,在多线程环境下需要特别小心,因为虽然它会强引用关联对象,但不保证原子性操作。如果要确保原子性,可以考虑使用OBJC_ASSOCIATION_RETAINOBJC_ASSOCIATION_RETAIN会强引用关联对象并且保证原子性,适合多线程环境下对关联对象的访问。
  2. 添加同步机制
    • 使用锁:可以使用NSLockNSRecursiveLock@synchronized等锁机制。例如,@synchronized关键字使用起来比较简洁,它会自动管理锁的生命周期。
    • 使用GCD队列:将对关联对象的操作都放在一个串行队列中执行,这样可以避免多线程竞争。

代码示例

  1. 使用@synchronized
#import <Foundation/Foundation.h>

@interface MyObject : NSObject
@end

@implementation MyObject
static char kAssociatedObjectKey;

- (void)setAssociatedObject:(id)object {
    @synchronized(self) {
        objc_setAssociatedObject(self, &kAssociatedObjectKey, object, OBJC_ASSOCIATION_RETAIN);
    }
}

- (id)associatedObject {
    @synchronized(self) {
        return objc_getAssociatedObject(self, &kAssociatedObjectKey);
    }
}
@end
  1. 使用GCD队列
#import <Foundation/Foundation.h>

@interface MyObject : NSObject
@end

@implementation MyObject
static char kAssociatedObjectKey;
dispatch_queue_t queue;

- (instancetype)init {
    self = [super init];
    if (self) {
        queue = dispatch_queue_create("com.example.associatedObjectQueue", DISPATCH_QUEUE_SERIAL);
    }
    return self;
}

- (void)setAssociatedObject:(id)object {
    dispatch_sync(queue, ^{
        objc_setAssociatedObject(self, &kAssociatedObjectKey, object, OBJC_ASSOCIATION_RETAIN);
    });
}

- (id)associatedObject {
    __block id result;
    dispatch_sync(queue, ^{
        result = objc_getAssociatedObject(self, &kAssociatedObjectKey);
    });
    return result;
}
@end