我有一个与iOs线程安全相关的令人费解的问题。
在单例对象中,我有一个包含字典元素的数组。字典元素包含与等待的资源相关的对象和字符串(从因特网下载的图像)。 当资源可用时(图像完成下载),我从数组中检索等待该特定资源的所有委托。
问题是数组(可变)可以非常频繁地修改(来自不同的线程),并且当它被枚举时它会被修改。
我该如何解决这个问题?我应该创建一个包含可变数组键的静态字典吗?但是仍然可以枚举给定键的特定数组,而某些东西会为它添加另一个值....
这是(非常不是线程安全的)代码:
- (void)addDelegate:(id<ImageDelegate>)delegate ForFileId:(NSString *)fileId
{
if (debug) { NSLog(@"[]adding delegate %@ for fileId: %@",delegate,fileId); }
NSDictionary *d = @{DELEGATE_KEY: delegate,
FILE_ID_KEY : fileId};
[self.delegatesArray addObject:d];
}
- (void)removeDelegate:(id<ImageDelegate>)delegate forImgUrl:(NSString *)imgUrl
{
NSString *fileId = [Utils formatLink:imgUrl];
if (debug) { NSLog(@"[]removing delegate %@ for fileId: %@",delegate,fileId); }
NSDictionary *toRemove;
for (NSDictionary *crtD in self.delegatesArray) {
if ([crtD[FILE_ID_KEY] isEqualToString:fileId] && [crtD[DELEGATE_KEY] isEqual:delegate]) {
toRemove = crtD;
break;
}
}
[self.delegatesArray removeObject:toRemove];
if (debug) { NSLog(@"[]removed delegate %@ for fileId: %@",toRemove,fileId); }
}
- (NSArray *)getAllDelegatesForFileId:(NSString *)fileId
{
NSMutableArray *requiredDelegates = [NSMutableArray new];
for (NSDictionary *crtD in self.delegatesArray) {
if ([crtD[FILE_ID_KEY] isEqualToString:fileId]) {
[requiredDelegates addObject:crtD];
}
}
NSArray *returnedArray = [NSArray arrayWithArray:requiredDelegates];
if (debug) { NSLog(@"[] found %d delegates for fileId:%@",[returnedArray count],fileId); }
return returnedArray;
}
答案 0 :(得分:0)
您有几个选择。
for
循环来迭代数组。这样的事情:
@synchronize (self.delegatesArray) {
// do something with the array
}
在数组的每个读/写访问权限周围使用上述内容
控制访问的另一种(更好的)方法是使用GCD。利用dispatch_sync
和dispatch_barrier_sync
。使用后者围绕写访问,前者围绕读访问。这样做的好处是允许多个读取器,但只允许一个写入器,并且在写入期间不会读取。