ZhangChn
ZhangChn

Reputation: 3184

multithread autorelease issue with ARC?

A class of service has a nonatomic property which is set in a serial queue.

@interface Service
@property (strong, nonatomic) NSDictionary *status;
@property (nonatomic) dispatch_queue_t queue;
...
@end

- (void)update:(NSDicationary *)paramDict {
    dispatch_async(self.queue, ^{
        ....
        self.status = updateDict;
    }
}


- (void)someMethod {
    NSDictionary *status = self.status;
}

The app crashed when the getter was invoked, at objc_autorelease + 6, which seems to be a runtime/Clang/llvm invocation.

And the crash log also showed that the status property was just set on the queue thread.

Did it crash because of the lack of atomicity in the accessors? If yes, how and why the getter failed retaining the instance? Did the autorelease pool get drained inside the synthesized nonatomic setter?

Should I implement the getter/setter method, protecting it with queue/a mutex lock?

Upvotes: 3

Views: 617

Answers (2)

Rob
Rob

Reputation: 437552

While atomic can address some integrity issues of fundamental data types in multi-threaded code, it's not sufficient to achieve thread-safety in general. Thread-safety is generally achieved through the judicious use of locks or queues. See the Synchronization section of the Threading Programming Guide. Or see Eliminating Lock-Based Code of the Concurrency Programming Guide that describes the use of queues in lieu of synchronization locks.

Assuming your queue is serial, you might be able to make it thread-safe by using the following construct:

- (void)someMethod {
    dispatch_sync(self.queue, ^{

        NSDictionary *status = self.status;

        // do what you need to with status
    });
}

That way, you're effectively using your serial queue to synchronize access to the status dictionary.

By the way, if your queue is a custom concurrent, you might also want to make sure that you replace the dispatch_async in paramDict to be dispatch_barrier_async. If your queue is serial, then dispatch_async is fine.

I'd suggest you try synchronizing your access to status, either using your queue or one of the synchronization techniques described in the Threading Programming Guide.

Upvotes: 1

Oh Seung Kwon
Oh Seung Kwon

Reputation: 431

If you don't mind, change the code like this.

nonatomic -> atomic

Upvotes: 1

Related Questions