NSMutableDictionary线程安全

Raj*_*Raj 39 objective-c nsmutabledictionary

我在使用时有一个关于线程安全的问题NSMutableDictionary.

主线程是从以下NSMutableDictionary位置读取数据:

  • 关键是 NSString
  • 价值是 UIImage

异步线程正在将数据写入上面的字典(使用NSOperationQueue)

如何使上面的字典线程安全?

我应该做的NSMutableDictionary财产atomic?或者我是否需要进行任何其他更改?

@property(retain) NSMutableDictionary *dicNamesWithPhotos;

not*_*oop 73

NSMutableDictionary不是设计为线程安全的数据结构,只是将属性标记为atomic,不能确保基础数据操作实际上是以原子方式(以安全的方式)执行的.

为确保每个操作都以安全的方式完成,您需要使用锁来保护字典上的每个操作:

// in initialization
self.dictionary = [[NSMutableDictionary alloc] init];
// create a lock object for the dictionary
self.dictionary_lock = [[NSLock alloc] init];


// at every access or modification:
[object.dictionary_lock lock];
[object.dictionary setObject:image forKey:name];
[object.dictionary_lock unlock];
Run Code Online (Sandbox Code Playgroud)

您应该考虑滚动自己NSDictionary,只需在持有锁的情况下将调用委托给NSMutableDictionary:

@interface SafeMutableDictionary : NSMutableDictionary
{
    NSLock *lock;
    NSMutableDictionary *underlyingDictionary;
}

@end

@implementation SafeMutableDictionary

- (id)init
{
    if (self = [super init]) {
        lock = [[NSLock alloc] init];
        underlyingDictionary = [[NSMutableDictionary alloc] init];
    }
    return self;
}

- (void) dealloc
{
   [lock_ release];
   [underlyingDictionary release];
   [super dealloc];
}

// forward all the calls with the lock held
- (retval_t) forward: (SEL) sel : (arglist_t) args
{
    [lock lock];
    @try {
        return [underlyingDictionary performv:sel : args];
    }
    @finally {
        [lock unlock];
    }
}

@end
Run Code Online (Sandbox Code Playgroud)

请注意,因为每个操作都需要等待锁定并持有它,所以它不是很可扩展,但在你的情况下它可能已经足够了.

如果要使用正确的线程库,可以使用TransactionKit库,因为它们TKMutableDictionary是一个多线程安全库.我个人还没有使用它,它似乎是一个正在进行中的工作库,但你可能想尝试一下.

  • bbum评论的后续行动.在Mike Ash的博客上有一篇关于在NSMutableDictionary上使用GCD并发队列的有用文章:http://mikeash.com/pyblog/friday-qa-2011-10-14-whats-new-in-gcd.html (6认同)
  • 很棒的答案.现在已经过时了.请改用队列.我在某个地方有一个简单的序列化字典.我应该发布它.消息转发缓慢且易碎. (5认同)
  • 如何使用@sychronized使其安全? (3认同)
  • 这看起来像一个很好的方法,但我无法编译.我正在''预期'''之前'retval_t'"`在线上` - (retval_t)转发:(SEL)sel:(arglist_t)args`任何想法? (2认同)

P.M*_*lch 5

现在你可能会去@synchronized(object)

...
@synchronized(dictionary) {
    [dictionary setObject:image forKey:name];
}
...
@synchronized(dictionary) {
    [dictionary objectForKey:key];
}
...
@synchronized(dictionary) {
    [dictionary removeObjectForKey:key];
}
Run Code Online (Sandbox Code Playgroud)

不再需要NSLock对象