0

I have code accessing and setting an NSDictionary many times across multiple threads, like so:

- (BOOL)flagForItem:(NSNumber*)itemID
{
    if(itemID) {
        return [[_itemFlagDict objectForKey:itemID] boolValue] 
    }
    return NO;
} 

and:

- (void)setFlagForItem:(NSNumber*)itemID
{
    if(itemID) {
        NSMutableDictionary *copy = [_itemFlagDict mutableCopy];
        [copy setObject:[NSNumber numberWithBool:YES] forKey:itemID];
        _itemFlagDict = [NSDictionary dictionaryWithDictionary:copy];
    }
}

In the set method, I originally had a NSMutableDictionary - this was changed to the pattern you see now because, doh, NSMutableDictionary isn't threadsafe. My reasoning was to perform the mutation in a copy, and then reassign the _itemFlagDict to capture the update.

However, occasionally a EXC_BAD_ACCESS crash still occurs when accessing the _itemFlagDict, leading me to believe that the dictionary is reassigned WHILE the accessing the objectForKey:itemID.

One other approach I tried was to use @synchronized(_itemFlagDict) on both the accessor and the setter methods. While this fixed the issue, this code is performance sensitive and synchronizing the access/assignment caused too much performance degradation.

So my question is, are there other patterns/methods I can use to avoid this bad access while not compromising performance? If prioritization matters, the execution (and not necessarily iron-clad accuracy) of the accessor method is most important.

Note: i'm working with iOS 4 and above

Dfowj
  • 739
  • 9
  • 25
  • Check out this answer http://stackoverflow.com/questions/1986736/nsmutabledictionary-thread-safety – MrShoot Jul 07 '12 at 04:57
  • That is a good example, but i've seen it before and i think the problem with it is that it locks on any selector being performed on the dictionary, which i dont want since reads will block as well as writes, which will slow performance – Dfowj Jul 09 '12 at 17:28
  • Have you tried read/write locks ? You can have multiple threads in your get methods and one writer in the set method. https://developer.apple.com/library/mac/#documentation/Darwin/Reference/ManPages/man3/pthread.3.html – Ali Mar 07 '13 at 20:19

2 Answers2

0

Have you tried read/write locks ? You can have multiple threads in your get methods and one writer in the set method https://developer.apple.com/library/mac/#documentation/Darwin/Reference/ManPages/man3/pthread.3.html

Ali
  • 1,503
  • 2
  • 15
  • 20
0

I have encountered the same problem, and my current solution is use Atomic operation to implement a thread-safe dictionary. You can check out it: https://github.com/bangquangvn/FastestThreadsafeDictionary-iOS

I think it's the fastest solution.