2011-10-05 57 views

回答

8

不,這完全不是線程安全的。由於對象是線程本地的,因此鎖定沒有效果。它需要被所有的調用線程共享。一旦你解決了這個問題,你不需要使用互鎖增量,因爲鎖串行化執行。

作爲一般規則,您應該將locker放在與您所保護的資源相同的級別。如果資源由實例擁有,那麼應該是locker。同樣如果資源是由班級擁有的話。

至於重新進入,lock關鍵字使用重入鎖,即如果鎖由該線程持有,則允許相同的線程進入。這可能不是你想要的。但是,如果你有一個不可重入的鎖,那麼你只能通過重入電話來鎖定自己。而且我不認爲你會這麼想。

你看起來像你想環繞增量。只要集合沒有被修改,這可以通過互鎖操作來實現,即免鎖。如果是這樣的話,就可以這樣寫:

do 
{ 
    int original = this.NextToExecuteIndex; 
    int next = original+1; 
    if (next == this.ReportingAgentsTypes.Count()) 
     next = 0; 
} 
while (Interlocked.CompareExchange(ref this.NextToExecuteIndex, next, original) != original); 

注:你應該申報NextToExecuteIndex揮發性。

+0

謝謝,我懷疑在本地範圍內聲明'locker'對象不是個好主意,但是我現在已經知道爲什麼了! =)'Poll'每個線程調用一次。我已將'locker'對象作爲實例私有變量移動。然而,閱讀你的答案我不知道這是好的,因爲該線程是在Poll的類的基類中創建的(遺憾的是雙撒克遜屬,聽起來很糟糕!)正在輪詢基類中抽象方法的重寫?所以'locker'在基類作用域中是不可訪問的,這是創建線程的地方?非常感謝。 –

+0

感謝David,在你的評論中閱讀你最後兩行(「你看起來像你想包裝...」),那麼我該如何改變它,以便檢查和重置爲0都是在原子操作中完成的。我可以想到的最好的是if(Interlocked.Increment(ref this.NextToExecuteIndex)> = this.ReportingAgentsTypes.Count()){this.NextToExecuteIndex = 0; \t}'但是當代碼進入'if'主體時,'NextToExecuteIndex'可能已經改變!非常感謝。 –

+2

評論1:你所做的事聽起來不錯。一個實例由基類和派生類組成。它仍然是同一個對象。那裏沒有問題。評論2:您需要比較和交換,因爲我編輯了要顯示的答案。 –

4

絕對不是。這是你的問題object locker = new object();。您將創建一個新對象並每次鎖定它。