我希望对我的应用程序有所帮助。
我有一个设置,其中多个线程访问单例类拥有的共享 NSMutableDictionary
。线程访问字典以响应下载 JSON 和处理它。单例类基本上可以防止复制一些具有唯一 ID 号的下载对象。
IE。
//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
是如何工作的,但我猜想后台有某种哈希表需要在分配对象时更新并在访问对象时读取。因此,如果线程要立即读取/写入字典,则可能会发生此错误 - 可能是因为对象已在内存中移动?我希望有更多关于该主题的知识的人可以启发我!
至于解决方案,我正在考虑具有最大并发操作数为 1 的
NSOperationQueue
的单例类,然后每当我想访问 operationWithBlock:
时使用 NSDictionary
。唯一的问题是它使调用 processJSON
成为一个异步函数,我不能立即返回创建的对象;我必须使用一个块,这会有点麻烦。有没有办法使用 @synchronize
?这样做会好吗? 最佳答案
我会提请您注意 Hot Licks 向您指出的线程编程指南的 iOS 版本的 Synchronization 部分。这些锁定机制之一,或使用专用串行队列,可以帮助您实现线程安全。
您对串行操作队列的直觉是有希望的,尽管人们经常为此使用串行调度队列(例如,您可以将 dispatch_sync
从任何队列调用到字典的串行队列),同时实现与它交互的受控机制作为同步操作。或者,更好的是,您可以使用自定义并发队列(不是全局队列),并通过 dispatch_sync
执行读取并通过 dispatch_barrier_async
执行写入,从而实现高效的读写器方案(如 WWDC 2011 - Mastering GCD 或 WWDC 2012 - Asynchronous Design Patterns 中所述)。
Concurrency Programming Guide 的 Eliminating Lock-Based Code 部分概述了使用串行队列进行同步与传统锁定技术的一些基本原理。
Concurrency Programming Guide 中的 Grand Central Dispatch (GCD) Reference 和 dispatch queue discussion 应该提供相当多的信息。
关于ios - NSMutableDictionary - EXC BAD ACCESS - 同时读/写,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/16137751/