2012-08-09 77 views
5

我有一個類,使用一個可變數組,經過大量的讀取(新項目到達)後修改一次。避免複製NSMutableArray讀取多線程寫入

問題是,當時代來突變數組,讀取不斷來。

目前以避免此問題每次讀的東西它這樣做在複印時間:

[[theArray copy] operation] //operation being indexOfObject:, objectAtIndex: objectsAtIndexes:, etc. 

副本將成爲真正昂貴,尤其是當有沒有必要(所有那些時候,數組是沒有被突變)。

如何鎖定數組,以便在突變時延遲對數組的訪問?

+0

爲什麼你不把這個數組作爲你的類的屬性,並且在聲明期間使它成爲原子,編譯器會處理線程之間的任何類型的同步。 – kidsid49 2012-10-21 18:30:14

回答

9

將所有數組訪問放入串行調度隊列。這將防止任何兩個操作同時發生。參見併發編程指南中的"Eliminating Lock-based Code"

如果您可以要求iOS> = 4.3,則可以使用併發自定義隊列和dispatch barriers進行變異操作。這將允許讀取同時發生,但是當需要寫入時,它們將被保持直到寫入完成。作爲障礙提交的塊本質上是在併發隊列上執行的 - 在所有先前塊完成之前它不會開始,也不會開始任何後續塊直到障礙塊完成。 (這是賈斯汀提到的讀寫鎖定的GCD版本。)我將你引導至無法模仿的Mike Ash samples of this

+1

正確完成,這允許並行讀取器和非阻止作者。這絕對是今天的首選解決方案。 – 2012-08-09 19:34:48

2

在這種情況下,您會考慮使用讀/寫鎖。可可不提供它們,但pthread_rwlock_t可用於pthreads接口 - 在pthread.h中聲明。請注意,這將比@synchronized更有效率(用於您的使用),甚至是簡單的鎖定。

5

最簡單的方法是使用@synchronized,像這樣:

-(void) accessTheArray { 
    MyClass *obj; 
    @synchronized(theArray) { 
     obj = [theArray objectAtIndex:...]; 
    } 
    [obj someMessage]; 
} 

編輯:如果不使用ARC,您可能希望保留/自動釋放的對象,否則它可能會從陣列中移除(併發布)之前someMessage被稱爲(感謝omz這個優秀的評論)。

+0

應該指出,儘管Xcode不能識別@synchronized作爲關鍵字,但它仍然有效。 – 2012-08-09 19:27:41

+0

如果不使用ARC,你可能想''保留'''autorelease'這個對象,否則可能會在調用someMessage之前將它從數組中移除(並釋放)。 – omz 2012-08-09 19:28:00

+0

@omz非常感謝你,這是一個非常重要的評論!像這樣的「小事」幫助我更全面地瞭解我的生活在ARC下更容易。 – dasblinkenlight 2012-08-09 19:33:21