ios - @sychronized 替代类方法

标签 ios synchronization grand-central-dispatch

我想要一个方法来创建一个新对象或返回一个基于标识符字符串的现有对象。

这是我的:

@implementation MyObject {

}

@synthesize data = _data;


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

// these methods are the only ones to be used for managing the MyObject life cycle

+ (NSMutableDictionary *)objectsDict
{
    static NSMutableDictionary *map = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        map = [NSMutableDictionary new];
    });
    return map;
}

+ (MyObject *)getRefrenceForId:(NSString *)identifier
{
    return [[MyObject objectsDict] objectForKey:identifier];
}

+ (MyObject *)newRefrenceWithId:(NSString *)identifier
{
    MyObject *obj;
    @synchronized (self) {
        obj = [[MyObject objectsDict] objectForKey:identifier];

        if (obj == nil) {
            obj = [[MyObject alloc] init];
            obj.identifier = identifier;
            [[MyObject objectsDict] setObject:obj forKey:identifier];
            NSLog(@"new instance of MyObject created with id:%@",identifier);  
        }

    }
    return  obj;
}

+ (MyObject *)newRefrenceWithId:(NSString *)identifier andClassType:(Class)classType
{
    MyObject *obj;
    @synchronized (self) {
        obj = [[MyObject objectsDict] objectForKey:identifier];

        if (obj == nil) {
            obj = [[MyObject alloc] initWithClassType:classType andId:identifier];
            [[MyObject objectsDict] setObject:obj forKey:identifier];
            NSLog(@"new instance of MyObject created with id:%@ of ClassType :%@",identifier,NSStringFromClass(classType));
        }
    }
    return obj;
}

+ (void)deleteInstance:(NSString *)identifier
{
    @synchronized (self) {
        [[MyObject objectsDict] removeObjectForKey:identifier];
    }
}

+ (void)clearAllMyObjectsFromMap
{
    @synchronized (self) {
        [[MyObject objectsDict] removeAllObjects];
    }
}

有更好的方法吗?我听说 @synchronized 的 CPU 开销很大,但是 GCD 并发队列不能用在类方法中...

更新:全局同步队列应该在哪里……在初始化中?那是一个实例方法,所以我不在那里工作......

最佳答案

您可以使用 GCD:

  1. 在模块范围内定义的自由函数中使用 dispatch_once 创建全局“同步队列”:

    static dispatch_queue_t get_sync_queue() {
        static dispatch_once_t onceToken;
        static dispatch_queue_t sync_queue;
        dispatch_once(&onceToken, ^{
            sync_queue = dispatch_queue_create("my.sync_queue", DISPATCH_QUEUE_CONCURRENT);
        });
        return sync_queue;
     }
    
  2. 将此队列与 dispatch_sync 和修改对象的 block 一起使用:

    + (MyObject *)newRefrenceWithId:(NSString *)identifier
    {
        __block MyObject *obj;
        dispatch_barrier_sync(get_sync_queue(), {
            obj = [[MyObject objectsDict] objectForKey:identifier];
    
            if (obj == nil) {
                obj = [[MyObject alloc] init];
                obj.identifier = identifier;
                [[MyObject objectsDict] setObject:obj forKey:identifier];
                NSLog(@"new instance of MyObject created with id:%@",identifier);  
            }
       });
       return  obj;
    }
    

方法 newRefrenceWithId: 现在是完全线程安全的。

编辑:

或者,您也可以使用并发 sync_queue 并在 block 中读取和写入时使用dispatch_barrier_sync(如您的情况)

写入对象时使用dispatch_barrier_async

如果您只需要读取 并返回共享对象的状态,您应该使用dispatch_sync - 它允许并发读取。

关于ios - @sychronized 替代类方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25021512/

相关文章:

objective-c - 串行调度队列中的 block 未执行 - GCD iOS Objective-C

ios - UIImage 缩放比例

java - 调用者阻塞直到 getFoo() 准备好一个值?

php - 多用户编辑器

swift - Dispatch.main.async "update the UI"怎么办?

ios - 您可以查询 GCD 串行队列以获取待处理任务的数量吗?

iphone - 表格 View 上下滚动时单元格顺序发生变化

ios - 如何获取当前显示的tableView的indexPath.row?

ios - IBOutlet 连接和继承

ios - 如何写一个软件同步文件到ipad