2011-08-16 32 views
6

我有一個關於蘋果(從的GameKit編程指南)下面的代碼示例的線程安全問題修改可變對象在完成處理

這是加載從遊戲中心成就和本地保存:

步驟1)添加一個可變的字典屬性到你的類,報告成就。這本詞典存儲了成就對象的集合。

@property(nonatomic, retain) NSMutableDictionary *achievementsDictionary; 

步驟2)初始化成績字典。

achievementsDictionary = [[NSMutableDictionary alloc] init]; 

步驟3)修改加載加載成就數據的代碼,將成就對象添加到字典中。

{ 
    [GKAchievement loadAchievementsWithCompletionHandler:^(NSArray *achievements, NSError *error) 
     { 
      if (error == nil) 
      { 
       for (GKAchievement* achievement in achievements) 
        [achievementsDictionary setObject: achievement forKey: achievement.identifier]; 
      } 
     }]; 

我的問題如下 - 在完成處理程序中正在修改achievementDictionary對象,沒有任何排序鎖定。這是否允許,因爲完成處理程序是一個工作塊,將由iOS保證在主線程上作爲單元執行?永遠不會遇到線程安全問題?在處理

@property (retain) NSMutableDictionary* earnedAchievementCache; // note this is atomic 

然後:

在另一個蘋果的示例代碼(GKTapper),這部分的處理方式不同

​​

那麼,爲什麼不同的風格,是一種方式更正確比其他?

回答

2

這是否被允許,因爲完成處理程序是一個工作塊,將由iOS保證在主線程上以單元執行?永遠不會遇到線程安全問題?

這絕對不是這種情況。 -loadAchievementsWithCompletionHandler:的文檔明確警告說完成處理程序可能在除了您開始加載的線程之外的線程上調用。

Apple的「線程編程指南」在線程不安全的類中對NSMutableDictionary進行了分類,但將其限定爲「在大多數情況下,只要您一次只從一個線程使用它們,就可以從任何線程使用這些類。 「

因此,如果兩個應用程序的設計都使得在工作任務完成更新之前什麼都不會與成就緩存一起工作,那麼就不需要同步。這是我能看到第一個例子是安全的唯一方法,而且這是一個脆弱的安全。

後一個示例看起來像是依賴原子屬性支持來在舊緩存和新緩存之間進行切換。這應該是安全的,只要通過訪問者訪問所有權,而不是直接訪問伊娃。這是因爲訪問者相互之間是同步的,所以你不會冒險看到一個半值的值。此外,getter保留並自動釋放返回的值,以便舊版本的代碼能夠完成對它的處理而不會崩潰,因爲它是在其工作中間發佈的。非原子getter直接返回對象,這意味着如果另一個線程爲該屬性設置了新的值,則可以從您的代碼中釋放該對象。直接ivar訪問可能會遇到同樣的問題。

我會說後一個例子既正確又優雅,雖然也許有點過分微妙而沒有評論解釋財產的原子性有多關鍵。

+0

謝謝傑里米。一般來說,我也在質疑塊完成處理程序。如果文檔沒有明確說明完成處理程序被調用的位置,那麼可以安全地假設它沒有在主線程中調用?如果指定從主隊列中調用,那麼在不擔心線程安全的情況下(假設所有訪問都來自主線程或主隊列上調用的處理程序處理程序),在內部執行任何操作都是安全的。 –

+0

如果它沒有指定你的塊將在主隊列/線程上被調用,那麼你必須採取自己的措施來確保它是,如果這是你所需要的。它可能實際上在主線程中被調用,但是在那一點上,這個事實是一個實現細節,而不是API合約的一部分,並且可能在沒有警告的情況下改變。如果指定從主隊列中調用,那麼您可以充分利用這一點。 –

+0

最後一個問題 - 如果我改變第一個完成處理程序使用dispatch_async(dispatch_get_main_queue(),^ {for(GKAchievement * achievement in achievement) [achievementDictionary setObject:achievement forKey:achievement.identifier];});) will this代碼也是線程安全的?我記得讀過一些關於這個不安全的東西.. –

相關問題