我有一个非常很少发生的错误,其中NSMutableDictionary
实例中的某个键最终指向错误的对象(同一个字典中的另一个对象)。
“关键混乱”可能是竞争条件的结果吗?
这是代码(因为我已经提出了新的线程安全性):
- (NSNumber*) makeHashFromResizedImage:(UIImage*)original newSize:(CGSize)newSize {
int retVal = original.hash + newSize.width * 2 + newSize.height * 4;
return [NSNumber numberWithInteger:retVal];
}
- (UIImage *)resizeImage:(UIImage*)image newSize:(CGSize)newSize {
NSNumber *key = [self makeHashFromResizedImage:image newSize:newSize];
if ([self.resizedImages objectForKey:key]) {
return [self.resizedImages objectForKey:key];
}
UIImage *newImage = {{image-resizing-code-here}};
[self.resizedImages setObject:newImage forKey:key];
return newImage;
}
注意:{{image-resizing-code-here}}
已删除,以简洁起见。我开始怀疑我的makeHashFromResizedImage
,因为它可能无法按预期工作。现在去单元测试。
答案 0 :(得分:2)
罗布说;你需要自己提供排除。
是的,“关键混乱”可能是竞争条件的结果,但这种可能性极小。更有可能的是,你最终会发生间歇性崩溃。但是,当然,由于腐败和未定义的行为,错误的价值可能会发生。
答案 1 :(得分:2)
此:
if ([self.resizedImages objectForKey:key]) {
return [self.resizedImages objectForKey:key];
}
如果另一个名为setObject:forKey:
的线程key
,第二行的结果将与第一行不同。为什么不将它存储在一个变量中呢?至少你检查的东西和你返回的东西都是一样的。
UIImage* image = [[[[self.resizedImages objectForKey:key] retain] autorelease];
if (image) {
return image;
}
(retain
+ autorelease
只是为了保留image
,在此线程运行时不会-dealloc
。)
如果您必须确保在函数返回之前不会覆盖与key
对应的image
,则需要使用锁定,而其他人则应答。
编辑:也许您应该使用UIImage的NSMutableSet。特别是,不要使用哈希值作为键!当两个对象不相同时,哈希值不需要不同。创建一个包含CGSize和UIImage属性的新类X,如果可以多次添加相同的UIImage,则使用X的NSMutableSet。
答案 2 :(得分:-1)
NSMutableDictionary
不是线程安全的。由你来提供锁定。