2013-05-20 25 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