我希望对我的应用程序有所帮助。
我有一个设置,其中多个线程访问一个共享的 NSMutableDictionary
由单例类拥有。线程访问字典以响应下载 JSON 并对其进行处理。单例类基本上可以防止某些具有唯一 ID 号的下载对象的重复。
即。
//NSURLConnection calls:
[[Singleton sharedInstance] processJSON:data];
@interface Singleton
+ (Singleton) sharedInstance;
@property (nonatomic, strong) NSMutableDictionary *store;
@end
@implementation
-(void) processJSON:(NSData*)data {
...
someCustomClass *potentialEntry = [someCustomClass parse:data];
...
if(![self entryExists:potentialEntry.stringId])
[self addNewEntry:potentialEntry];
...
}
-(void) entryExists:(NSString*)objectId {
if(self.store[objectId])
return true;
else return false;
}
-(void) addEntry:(someCustomClass *object) {
self.store[object.stringId] = object;
}
一次可以有多达 5-10 个线程同时调用 processJSON。
不是立即,而是在运行几分钟后(在 iPhone 上比在模拟器上更快)我得到了可怕的 EXC BAD ACCESS。
我不承认我知道如何NSMutableDictionary
有效,但我猜想在后台有某种哈希表需要在分配对象时更新并在访问对象时读取。因此,如果线程要立即读取/写入字典,则可能会发生此错误 - 可能是因为对象已在内存中移动?
希望有这方面知识的高手赐教!
至于解决方案,我正在考虑具有 NSOperationQueue
的单例类最大并发操作数为 1 然后使用 operationWithBlock:
每当我想访问 NSDictionary
.唯一的问题是它会调用 processJSON
一个异步函数,我不能立即返回创建的对象;我必须使用一个 block ,那会有点困惑。有什么方法可以使用 @synchronize
?这样效果好吗?
最佳答案
我会提请您注意 Synchronization Hot Licks 向您指出的 线程编程指南 的 iOS 版部分。其中一种锁定机制或使用专用串行队列可以帮助您实现线程安全。
您对串行操作队列的直觉很有希望,尽管人们经常为此使用串行调度队列(例如,因此您可以从任何队列调用 dispatch_sync
到字典的串行队列),实现既是一种与其交互的受控机制,也是一种同步操作。或者,更好的是,您可以使用自定义并发队列(不是全局队列),并通过 dispatch_sync
执行读取并通过 dispatch_barrier_async
执行写入,从而实现高效的读写器方案(如 WWDC 2011 - Mastering GCD 或 WWDC 2012 - Asynchronous Design Patterns 中所讨论)。
Eliminating Lock-Based Code 并发编程指南的部分概述了使用串行队列进行同步与传统锁定技术的一些基本原理。
Grand Central Dispatch (GCD) Reference和 dispatch queue discussion Concurrency Programming Guide 中应该提供了相当多的信息。
关于ios - NSMutableDictionary - EXC BAD ACCESS - 同时读/写,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16137751/