2010-09-03 111 views
2

請考慮以下情況:我在ASP.NET中使用Application對象來存儲由多個用戶同時訪問的集合(List(of MyObject))。而據我所知,從Application對象閱讀是線程安全的,我不知道我應該如何使此代碼線程安全的:我應該使用Application.Lock()嗎?

objList = Application("GlobalList") 

objList.add(AnotherValue) 

application("GlobalList") = objList 

objList = Application("GlobalList") 

dim PrunedList as MyObject() = (from o as MyObject in objList where o.SomeProperty = SomeValue).ToArray() 

objList.Clear() 

For each PrunedListObject as MyObject in PrunedList 
    objList.add(PrunedListObject) 
next 

application("GlobalList") = objList 

我讀了一些關於Application.Lock( )這基本上是一個互斥鎖,但我擔心阻止其他線程的性能影響,同時操縱Application("GlobalList")是Application.Lock()的正確方法?

回答

2

我並不是ASP.NET專家,但我確實使用了它幾年。應用程序存儲幾乎與傳統ASP向後兼容。你需要try/finally塊來鎖定和解鎖,並且它還不如使用.NET中其他一些在傳統ASP中沒有的鎖定機制那麼靈活。

在你的例子中,鎖定/解鎖需要非常廣泛,因爲即使你抓住了「GlobalList」,多個線程同時寫入這個集合仍然會導致併發問題。

但是一般來說,對集合的任何多線程讀/寫訪問本質上都是不安全的。你會有任何收集相同的問題。但是使用靜態字段,您可以讓多個線程以強類型的方式訪問各個值,而不需要字典所需的「魔術字符串」。你也不需要在很多情況下鎖定。

你可以做這樣的事情,根本不使用應用程序存儲。請注意,您仍然需要同步對集合的訪問,但不需要鎖定/解鎖整個應用程序狀態字典。

Private Shared GlobalList As New List(Of Foo)() 

... 

SyncLock GlobalList 
    // Only one thread can proceed here at a time 
End SyncLock 

如果性能不會成爲影響由於多個讀者阻止對方即使沒有寫入是怎麼回事,你可以切換到使用讀寫鎖。在.NET中有一個名爲ReaderWriterLockSlim的實現,它允許多個閱讀器同時執行,只要沒有寫者持有該鎖。當讀者多於作者時,這會顯着提高您的表現。使用這種類型的鎖有點麻煩,因爲沒有像C#的鎖語句或VB的SyncLock這樣的語法糖。

編輯

正如下面的評論中指出,你應該考慮的性能影響任何鎖定的策略使用。尤其是,ReaderWriterLockSlim實際上可能會降低性能,如果讀者之間沒有太多的爭用。以下是MSDN比較Monitor和ReaderWriterLockSlim的文章。 http://blogs.msdn.com/b/pedram/archive/2007/10/07/a-performance-comparison-of-readerwriterlockslim-with-readerwriterlock.aspx

+1

雖然我一般同意Josh的回答,但在讀/寫方案中鎖被鎖定了很短的時間,'lock'語句仍然勝過'ReaderWriterLockSlim'(即使沒有寫入) 。當鎖內的時間足夠大時(根據http://tinyurl.com/rwlsperformance,調用大約100個不可插入的空方法),'ReaderWriterLockSlim'將會很有用。不僅可以讓用戶更快地「鎖定」你的代碼,更重要的是,它可以讓你更容易理解。 – Steven 2010-09-03 14:32:51

+1

@Steven:我同意。我的個人測試表明,當關鍵部分能夠以快速和快捷的方式執行時,「ReadWriterLockSlim」比普通的舊'lock'慢大約5倍。添加和刪​​除「List」中的項目幾乎肯定會很快捷。否則,這通常是一個很好的答案。 – 2010-09-03 16:24:17

+1

嗨,大家好,感謝您對ReaderWriterLockSlim的反饋。我知道舊的執行方式只是一條狗,但我認爲他們已經更接近於Monitor在新的實施方面的表現。無論如何,除非性能測試另有說明,否則我總是會採用最簡單的機制。 – Josh 2010-09-03 17:11:24