2013-05-20 24 views
3

服务类具有设置在串行队列中的非原子属性。ARC的多线程autorelease问题?

@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; 
} 

该应用程序崩溃被调用getter方法时,在objc_autorelease + 6,这似乎是一个运行时/锵/ LLVM调用。

并且崩溃日志还显示status属性刚设置在queue线程上。

是否因为访问器中缺乏原子性而崩溃?如果是,那么如何以及为什么吸气剂保留实例失败?自动释放池是否在合成的非原子设定器内部排空?

我应该实施getter/setter方法,使用queue/mutex锁来保护它吗?

+0

什么是例外? – Rob

回答

1

虽然atomic可以在多线程代码解决基本数据类型的一些完整的问题,这不是足以实现普通线程安全。线程安全通常通过明智地使用锁或队列来实现。请参阅“线程编程指南”的Synchronization部分。或参见并发编程指南Eliminating Lock-Based Code,其描述了使用队列来代替同步锁。

假设您的队列是串行的,你也许能够使它线程安全使用下面的结构:

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

     NSDictionary *status = self.status; 

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

这样一来,你就有效地利用您的串行队列同步访问status字典。顺便说一下,如果您的队列是自定义并发队列,那么您可能还需要确保将paramDict中的dispatch_async替换为dispatch_barrier_async。如果你的队列是串行的,那么dispatch_async是好的。

我建议您尝试使用您的队列或线程编程指南中描述的同步技术之一来同步您对status的访问。

+0

我同意在这种情况下调度队列通常很好。但是,我并不完全确定崩溃是否由违反线程安全或不是由于线程安全造成的。 – ZhangChn

+0

@ ZhangChn哦,是的,我同意。我很抱歉忽视这个相当基本的观点。例外的来源并不十分清楚。我只是对原子v非原子的重点做出反应。话虽如此,值得让这个线程安全:无论如何你必须这样做,它可以解决这个问题。 – Rob

1

如果您不介意,请像这样更改代码。

非原子 - >原子

+0

我没有经验在iOS上使用原子属性,因为它建议不要。 'atomic'如何影响iOS上访问器方法的行为? – ZhangChn

+0

等一下,我应该检查一下。感谢您的回应。 –

+1

请参阅http://stackoverflow.com/questions/588866/atomic-vs-nonatomic-properties – Rob