2011-01-12 48 views
10

我知道Index對象的邊界錯誤之外的一個主要原因是線程衝突。 (同時閱讀和寫同一詞典)然而,我遇到了一個令人困惑的案例,那裏的線程衝突並不是一個足夠的解釋。Index的替代原因超出了.Net字典中數組的邊界

以下是這種情況: 我已經編寫了一些代碼,以不安全的方式爲多線程處理實現Dictionary。

該代碼已作爲Web服務實現到兩臺服務器Server A和Server B.服務器通過負載均衡器訪問,負載均衡器以循環方式向服務器A和B發送請求。

現在,這裏是棘手的部分。錯誤只出現在服務器A上,而從不在服務器B上。根據我們的硬件團隊,兩臺服務器都是相同的。雖然線程衝突本質上是一個隨機過程,但它仍然應該同樣影響我的服務器。我在一臺服務器上看到50多個錯誤實例,另一臺服務器上發生了0個錯誤。從統計上來看,線程衝突只發生在我的一臺服務器上,而另一臺服務器則無錯誤運行。

我已經在修改應用程序以使其線程更安全,但是在Dictionary對象的Insert操作中拋出此錯誤的其他原因可能存在嗎?

+0

您確定負載平衡器向服務器B發送請求嗎?可能它隻影響第一臺服務器。 –

+0

也許一臺服務器有一個32位的操作系統,另一臺是64位的? –

+0

@ petro.sidlovskyy我已經確認兩臺服務器都有基於日誌文件的流量 – Joshua

回答

7

雖然線程衝突本質上是一個隨機過程

不是。它嚴重依賴於時機。時間可以重複,系統傾向於解決特定的模式。像Microsoft Research的CHESS這樣的線程競爭診斷工具通過在線程的執行中注入隨機延遲來工作。讓系統脫離這種模式。就像它偶爾自己做的一樣,但每週只有一次。 是隨機的,只是沒有足夠的隨機性給你一個調試問題。

因此,看到一個服務器失敗,而不是其他並不意味着什麼。負載平衡器可能與它有關。你永遠無法找出確切的原因,因爲你無法找出這些發生了50次的事情。這還不夠。

1

這可能是牽強的,但是你碰巧知道你的連接通過負載均衡器向兩臺服務器是否相等? (我真的不知道負載平衡如何工作,所以這可能是一個愚蠢的想法從起點。)

我只是想,說你有更多的網絡延遲在你的連接到服務器B而不是服務器A.這可以在該服務器上的客戶端請求之間提供足夠的距離,從而實現字典訪問,讓您擺脫多線程代碼的不安全感。

如果請求更快地到達服務器A,這可能會導致超出範圍的錯誤。

就像我說的,可能牽強 - 只是一個想法。我認爲把它扔到那裏並不會讓人傷心。

0

我無法解釋爲什麼它不能在一臺服務器上工作,而不能在另一臺服務器上工作。你的問題是多線程問題。

正如你可能已經注意到,這不會在多線程環境中工作:

if (!dict.ContainsKey("myKey")) 
    dict.Add("myKey", value); 

也是一樣的:

if (dict.ContainsKey("myKey")) 
    return dict["myKey"]; 

什麼可能的驚喜,你是TryGetValue不是線程安全的或者:

MyObject obj; 
return dict.TryGetValue("myKey", out obj) ? obj : null; 

參考:http://www.grumpydev.com/2010/02/25/thread-safe-dictionarytkeytvalue/

+0

它不應該讓你感到驚訝,因爲它們在第一種情況下不是線程安全的集合? – Kurru

相關問題