首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >类方法中的@sychronized

类方法中的@sychronized
EN

Stack Overflow用户
提问于 2014-07-30 01:32:24
回答 1查看 200关注 0票数 2

我希望有一个基于标识符串创建新对象或返回现有对象的方法。

这就是我所拥有的:

代码语言:javascript
复制
@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并发队列不能用在类方法中……

更新:全局同步队列应该放在哪里。在init中?这是一个实例方法,所以我不会在那里工作。

EN

回答 1

Stack Overflow用户

发布于 2014-07-30 03:54:36

您可以使用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;}

  • 使用此队列和修改object:

  • (MyObject的块*)newRefrenceWithId:(NSString *)identifier { __block MyObject * obj;dispatch_barrier_sync(get_sync_queue(),{ obj = [MyObject objectsDict objectForKey:identifier];if (obj == nil) {obj= [MyObject alloc ];obj.identifier = identifier;[MyObject objectsDict setObject:obj forKey:identifier];NSLog(@“新创建的MyObject实例id:%@",identifier);} });return obj;}

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

编辑:

或者,您也可以在读写块时使用并发sync_queue和dispatch_barrier_sync (与您的示例相同)。

在编写对象时使用dispatch_barrier_async

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

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/25021512

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档