锁定与并发
?????在多線程程序中,我們經常需要對要訪問的資源進行加鎖。加鎖的目的是為了同步對資源的訪問,但是,加鎖不可避免的會降低應用的并發量。那么如何在需要加鎖的時候,盡可能地提高并發量了?下面是我的一些經驗,僅供參考。
?1.首先,我們要控制好鎖的粒度。
?????鎖的粒度越大,能支持的并發就越小。
?????我們只需要將真正需要同步的代碼塊lock住,而不需要同步的代碼塊不要放在lock塊中。
?????當然,鎖的粒度也不是越小越好,粒度太細的鎖會導致編程很繁瑣,而且需要足夠的細心和全面考慮方可保證鎖不會出現問題。
?????在這點上,有一個特別需要注意的是 -- 事件。事件最好不要在lock塊中觸發,因為你無法確定組件應用者的事件處理函數會執行多久。除非,你對一切了然于胸。
????????????lock?(this.locker)????????????{
????????????????//
????????????????this.OnSomeEvent();?//觸發事件
????????????}
?
2.杜絕死鎖的發生。當發生死鎖時,并發將降到最低。
3.區分讀寫。
?????我們經常使用lock關鍵字來鎖定資源,然而,lock沒有辦法區分讀寫。比如,如果當前同時有三個線程在訪問資源,且三個都是讀取資源,如果使用lock,那么,在讀取資源上,它們也會被同步處理。幸運的是,.NET為我們提供了讀寫鎖 -- ReaderWriterLock?,使用它,上面的例子便是三個線程可以同時讀取資源。
?????對于那種讀取多于修改的資源,區分讀寫可以極大地提升并發量。
?????ReaderWriterLock的使用不如lock來得方便,為此,我封裝了SmartRWLocker,它提供了和ReaderWriterLock一樣的功能,但是我們可以像使用lock一樣來使用它,如:?
??????????? using(this.smartRWLocker.Lock(AccessMode.Read))????????????{
????????????????//do?something
????????????}
?????SmartRWLocker的實現也相當簡單,如下所示:
???? ///?<summary>
????///?SmartRWLocker?簡化了ReaderWriterLock的使用。zhuweisky?2008.11.25
????///?</summary>
????public?class?SmartRWLocker
????{
????????private?ReaderWriterLock?readerWriterLock?=?new?ReaderWriterLock();
????????public?LockingObject?Lock(AccessMode?accessMode)
????????{
????????????return?new?LockingObject(this.readerWriterLock,?accessMode);
????????}
????}???
????///?<summary>
????///?AccessMode?訪問鎖定資源的方式。
????///?</summary>
????public?enum?AccessMode
????{???????
????????Read?=?0,
????????Write
????}
????{
????????private?ReaderWriterLock?readerWriterLock;
????????private?AccessMode?accessMode?=?AccessMode.Read;
????????#region?Ctor
????????public?LockingObject(ReaderWriterLock?_lock,?AccessMode?_lockMode)
????????{
????????????this.readerWriterLock?=?_lock;
????????????this.accessMode?=?_lockMode;
????????????if?(this.accessMode?==?AccessMode.Read)
????????????{
????????????????this.readerWriterLock.AcquireReaderLock(-1);
????????????}
????????????else
????????????{
????????????????this.readerWriterLock.AcquireWriterLock(-1);
????????????}
????????}
????????#endregion
????????#region?IDisposable?成員
????????public?void?Dispose()
????????{
????????????if?(this.accessMode?==?AccessMode.Read)
????????????{
????????????????this.readerWriterLock.ReleaseReaderLock();
????????????}
????????????else
????????????{
????????????????this.readerWriterLock.ReleaseWriterLock();
????????????}
????????}
????????#endregion
????}
?
?
?2009.02.23 附加:
?????我們都知道,對于集合類,如Lits<>,Dictionary<,>等,
(1)如果其它線程在對其中的元素進行修改(如添加或刪除元素)時,正在對集合進行枚舉的線程會拋出異常。
(2)如果有一個線程正在對集合進行修改,另外一個線程調用Contains/ContainsKey,會拋出異常嗎?答案是不會。
?
?
?
?
轉載于:https://www.cnblogs.com/zhuweisky/archive/2008/11/26/1341154.html
總結
- 上一篇: 衡量发动机性能的重要指标—升功率
- 下一篇: Asp.Net收集