2013-10-18 125 views
3

我遇到了線程安全問題。我有一個隊列,當我修改內容導致跨線程錯誤。我之前沒有使用鎖,但是我想我會嘗試。我在所有爲我的隊列操作NSMutableArray的代碼上添加了一個鎖。我認爲這個問題是我沒有對它們全部使用相同的鎖。我在每個修改數組的方法中創建了一個新的NSLock實例。我假設我應該使用一個NSLock ivar來保護陣列。但是我的困惑來自事實,一旦我添加它就行了。以下是一個示例。我認爲無處不在,我創建了一個新的NSLock,我應該只使用一個伊娃NSLock。我認爲這段代碼只是鎖定了其他排隊隊列和出隊隊列,而不是排隊隊列。澄清會很好。不正確使用NSLock,但似乎仍然有效

@implmentation 

...  

- (void)enqueue:(id)obj 
{ 
    NSLock *arrayLock = [[NSLock alloc] init]; 
    [arrayLock lock]; 
    [_backingStore addObject:obj]; 
    [arrayLock unlock]; 
} 

- (id)dequeue 
{ 
    NSLock *arrayLock = [[NSLock alloc] init]; 
    [arrayLock lock]; 
    id result = [_backingStore firstObject]; 

    if(result) 
    { 
    [_backingStore removeObjectAtIndex:0]; 
    } 

    [arrayLock unlock]; 
    return result; 
} 

... 

@end 

回答

5

是的,你需要使用相同的NSLock實例來鎖定對數組的訪問。與許多多線程錯誤一樣,由於添加附加代碼導致時間差異,問題可能似乎消失。或者,這可能只是因爲你得到了(非)幸運,並且當你第二次測試時問題沒有出現。

無論值得什麼,NSLock只是鎖定Objective-C中關鍵部分的一種方法。您還可以使用@synchronized()這可能是從一個代碼複雜點容易:

@synchronized(someSharedToken) { 
    // Do your array access here 
} 

你也可以使用一個串行調度隊列序列化對資源的訪問。這有幾個優點,其中最重要的就是無需等待該工作在當前線程上完成即可派發工作。派遣工作到隊列的費用也比取出鎖定要便宜。請參閱Apple的「併發編程指南」的Creating Serial Dispatch Queues部分。

+0

感謝您的回答。我打算搬到派遣隊列。我想過使用@synchronized,但認爲它帶來了額外的異常處理開銷。由於必須使用相同的實例,這是否意味着在我的示例中兩個線程是否調用enqueue方法,既不會阻止另一個線程,因爲每個方法調用都會創建自己的實例? – Brian

+2

是的。你可以看到我在這裏放置的快速和骯髒的例子:https://gist.github.com/armadsen/7045187。 –

+0

感謝這個例子。 – Brian

相關問題