2013-01-07 163 views
0

我有用C#編寫的應用程序,雖然任何類似的語言都適用於此。多線程最佳實踐

應用程序有繪製圖形場景到的窗口基於數據的實時接收通過各種UDP和TCP套接字窗體上的工作。每個UDP和TCP連接使用它自己的線程:這些線程各自修改內存中的各種對象,從而修改圖形顯示。我也有一個用戶界面線程,它能夠接收用戶事件(按鈕點擊等),然後修改這些相同的對象和顯示。最後,我還有很多定時器,我會啓動它們自己的線程來修改這些相同的對象和顯示。

在存儲器正在修改的目的由約15種不同的類。

一切工作非常可靠,但是所有這些不同類別的被不同的線程修改,我不得不添加了很多同步鎖。我不得不逐個查看每個類,以確定哪個內存可能被多個線程修改。

這似乎很容易在這種情況下錯過這些景點之一:忘記的地方加上同步它的需要。

我很好奇,別人是否會實現這個我做的方式,或者,如果有一些更優雅的方式:也許在某種程度上將所有A類的修飾對自己的線程或東西嗎?

(PS我很害怕在第一次事情沒有那麼好之後問一個問題,但我不認爲我的問題在這裏顯得非常明顯,所以我希望你不會o)

回答

1

我相信對此沒有直接的答案。

我幫助其他人改變設計來處理類似的情況。最常用的技術之一是引入更好的抽象。例如,假設您有多個線程需要更新包含用戶的Map,另一個Set包含活動用戶,而不是爲用戶映射和活動用戶集設置鎖定,並讓您的線程手動獲取鎖定,我會建議引入一個抽象調用UserRepository,其中包含用戶映射和活動用戶集。 UserRepository將爲其他人操作UserRepository提供一些有商業意義的方法。鎖在UserRepository的方法中獲得,而不是由調用者明確獲取。

從我過去的經驗來看,有80%以上的複雜同步可以通過像上面提到的例子那樣有更好的設計來大大簡化。

也有其他技術可能。例如,如果更新可以異步執行,而不是讓線程直接更新資源,則可以創建命令對象並放入生產者 - 消費者隊列中,並且有一個專用線程執行更新。

有時候更容易處理以減少鎖。例如,在更新多個資源時,不是每個資源都有一個鎖,我們可以將整個更新視爲一個整體操作,並且只使用一個鎖進行線程之間的協調。當然這會增加爭用,但有些情況下爭用並不是一個大問題,但我們需要可維護性。

我相信有很多其他的方式來處理類似的情況,我只是分享一些我以前的經驗(它的工作:P)

+0

感謝這麼多強勁的答案。這是一個非常好的話題討論。 – vmayer