Search code examples
objective-ccocoa-touchcocoaobjective-c-blockscocoa-design-patterns

Objective-C __block keyword and thread-safety


I'm wondering how I can make access to a __block qualified var thread-safe within the context of a method.

Example:

__block NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];

for (int i=0; i<20; i++) {
    NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{
        [dictionary setObject:@"test" forKey:@"test"];
    }];
    [someConcurrentQueue addOperation:operation];
}

Here the operation is added to a concurrent queue and the dictionary var will potentially be accessed from different threads at the same time.

Is this safe? If not, how do I make access to dictionary safe?


Solution

  • As UIAdam said in his comment, __block isn't doing anything for you here; you're mutating the dictionary, not assigning to the variable. The variable will continue to point to the same dictionary forever.

    In fact, __block may actually hurt you here, since it means the variable will not be captured by the block. If you're not using ARC, this means the dictionary will not be retained, and the block may be sending messages to a dead object soon. I'm not sure offhand whether ARC changes this. At any rate, you should leave __block off of this variable; if nothing else, the code more clearly expresses your intent without it.

    As for your actual question, about thread-safety, this code is not safe. According to the Thread-Safety Summary, the mutable collection classes are not thread-safe: you must send messages to a mutable collection from no more than one thread at a time. Synchronization would be one way; setting the queue's max concurrent operation count to 1 would be another.