0

この投稿リンクからの参照 NSMutableDictionary を使用して必要な情報を保存するという同じ概念を使用して、同様のカテゴリを実装しました。しかし、元の投稿で私を混乱させることが1つあります

- (NSMutableDictionary *)addl_associatedDictionary
{
     NSMutableDictionary *res = nil;
     @synchronized(self) 
     {
        if (!(res = [self addl_associatedDictionaryPrimitive])) 
        {
           res = [self addl_generateAssociatedDictionary];
        }
     }
    return res;
}

@synchronized キーワードが mutilthread の保護であることは知っています。しかし、他の例を見ていくと、ほとんどは保護を使用しませんでした。それで、保護は必要ですか?また、静的dispatch_once_tを使用して@synchronizedを置き換えることはできますか? 以下は.mファイルの私のコードスニップです

@dynamic associatedDict;

-(void)setAssociateValue:(NSMutableDictionary*)dict
{
    objc_setAssociatedObject(self, @selector(associatedDict), dict,   OBJC_ASSOCIATION_RETAIN);
} 

-(id)getAssociateValue
{
    return objc_getAssociatedObject(self, @selector(associatedDict));
}

-(NSMutableDictionary*)associatedDict
{
    NSMutableDictionary* dict=[self getAssociateValue];
    if(!dict)
    {
       dict=[[NSMutableDictionary alloc]init];
       [self setAssociatedDict:dict];
    }
    return dict;
 } 


 -(void)setAssociateDict:(NSMutableDictionary *)associatedDict
{
    [self setAssociatedDict:associatedDict];
}

-(id)associate_getObjectForKey:(NSString*)key
{
    return self.associatedDict[key];
}

-(void)associate_setObject:(id)obj forKey:(NSString*)key
{
   [self.associatedDict setObject:obj forKey:key];
}
4

2 に答える 2

1

ロック コストに関する暗黙の懸念に答えるのに役立つかもしれませOBJC_ASSOCIATION_RETAINOBJC_ASSOCIATION_RETAIN_NONATOMIC@synchronize後者を使用している場合、前者のロックを差し控えることができるという点で、それは冗長に見えるでしょう。現時点では、同期のために 2 倍の料金を支払っています。一度支払うか、まったく支払わないかのどちらかです。

最善の全体的な解決策は次のとおりです。

NSMutableDictionary *res; // no need to assign to `nil`; it's implied in ARC

// you're using an atomic property, so this is inherently safe
if (!(res = [self addl_associatedDictionaryPrimitive])) 
{
    // okay, doesn't exist, but two or more threads may get to
    // here simultaneously so we'll need to synchronise, and...
    @synchronized(self) 
    {
        // ... check again. As someone else may already have proceeded past the
        // outer if and created it while this thread was waiting to
        // enter the synchronised block. Assuming this dictionary
        // is created more rarely than it's accessed, this is no great issue
        if (!(res = [self addl_associatedDictionaryPrimitive])) 
        {
           res = [self addl_generateAssociatedDictionary];
        }
    }
}
return res;

...そして固執しOBJC_ASSOCIATION_RETAINます。また、CRD の指摘にも注意してください。変更可能な辞書自体はスレッド セーフではありません。したがって、実際にスレッドセーフが必要な場合、これで問題が正確に解決されるわけではありません。スレッド セーフが必要ない場合は、に切り替えてOBJC_ASSOCIATION_RETAIN_NONATOMICダンプし@synchronizedます。

于 2015-07-02T19:54:55.413 に答える