下面的代碼是可重入的嗎?以下代碼是否可重入且線程安全?
是否線程安全,如果this.NextToExecuteIndex
宣佈爲private int NextToExecuteIndex = 0;
而不是在其他地方計算?
下面的代碼是可重入的嗎?以下代碼是否可重入且線程安全?
是否線程安全,如果this.NextToExecuteIndex
宣佈爲private int NextToExecuteIndex = 0;
而不是在其他地方計算?
不,這完全不是線程安全的。由於對象是線程本地的,因此鎖定沒有效果。它需要被所有的調用線程共享。一旦你解決了這個問題,你不需要使用互鎖增量,因爲鎖串行化執行。
作爲一般規則,您應該將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
揮發性。
絕對不是。這是你的問題object locker = new object();
。您將創建一個新對象並每次鎖定它。
謝謝,我懷疑在本地範圍內聲明'locker'對象不是個好主意,但是我現在已經知道爲什麼了! =)'Poll'每個線程調用一次。我已將'locker'對象作爲實例私有變量移動。然而,閱讀你的答案我不知道這是好的,因爲該線程是在Poll的類的基類中創建的(遺憾的是雙撒克遜屬,聽起來很糟糕!)正在輪詢基類中抽象方法的重寫?所以'locker'在基類作用域中是不可訪問的,這是創建線程的地方?非常感謝。 –
感謝David,在你的評論中閱讀你最後兩行(「你看起來像你想包裝...」),那麼我該如何改變它,以便檢查和重置爲0都是在原子操作中完成的。我可以想到的最好的是if(Interlocked.Increment(ref this.NextToExecuteIndex)> = this.ReportingAgentsTypes.Count()){this.NextToExecuteIndex = 0; \t}'但是當代碼進入'if'主體時,'NextToExecuteIndex'可能已經改變!非常感謝。 –
評論1:你所做的事聽起來不錯。一個實例由基類和派生類組成。它仍然是同一個對象。那裏沒有問題。評論2:您需要比較和交換,因爲我編輯了要顯示的答案。 –