在多線程程序中,我們經(jīng)常需要對(duì)要訪問(wèn)的資源進(jìn)行加鎖。加鎖的目的是為了同步對(duì)資源的訪問(wèn),但是,加鎖不可避免的會(huì)降低應(yīng)用的并發(fā)量。那么如何在需要加鎖的時(shí)候,盡可能地提高并發(fā)量了?下面是我的一些經(jīng)驗(yàn),僅供參考。
1.首先,我們要控制好鎖的粒度。
鎖的粒度越大,能支持的并發(fā)就越小。
我們只需要將真正需要同步的代碼塊 lock 住,而不需要同步的代碼塊不要放在lock塊中。
當(dāng)然,鎖的粒度也不是越小越好,粒度太細(xì)的鎖會(huì)導(dǎo)致編程很繁瑣,而且需要足夠的細(xì)心和全面考慮方可保證鎖不會(huì)出現(xiàn)問(wèn)題。
在這點(diǎn)上,有一個(gè)特別需要注意的是 -- 事件。 事件最好不要在lock塊中觸發(fā),因?yàn)槟銦o(wú)法確定組件應(yīng)用者的事件處理函數(shù)會(huì)執(zhí)行多久。 除非,你對(duì)一切了然于胸。
{
//

this .OnSomeEvent(); // 觸發(fā)事件
}
2.杜絕死鎖的發(fā)生。當(dāng)發(fā)生死鎖時(shí),并發(fā)將降到最低。
3.區(qū)分讀寫。
我們經(jīng)常使用 lock 關(guān)鍵字來(lái)鎖定資源,然而,lock沒(méi)有辦法區(qū)分讀寫。比如,如果當(dāng)前同時(shí)有三個(gè)線程在訪問(wèn)資源,且三個(gè)都是 讀取 資源,如果使用lock,那么,在讀取資源上,它們也會(huì)被同步處理。幸運(yùn)的是,.NET為我們提供了讀寫鎖 -- ReaderWriterLock ,使用它,上面的例子便是三個(gè)線程可以同時(shí)讀取資源。
對(duì)于那種讀取多于修改的資源,區(qū)分讀寫可以極大地提升并發(fā)量。
ReaderWriterLock的使用不如lock來(lái)得方便,為此,我封裝了 SmartRWLocker ,它提供了和ReaderWriterLock一樣的功能,但是我們可以像使用lock一樣來(lái)使用它,如:
{
// dosomething
}
SmartRWLocker的實(shí)現(xiàn)也相當(dāng)簡(jiǎn)單,如下所示:
<!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->
///
<summary>
///
SmartRWLocker簡(jiǎn)化了ReaderWriterLock的使用。
zhuweisky2008.11.25
///
</summary>
public
class
SmartRWLocker
{
private
ReaderWriterLock
readerWriterLock
=
new
ReaderWriterLock
();
public
LockingObjectLock(
AccessMode
accessMode)
{
return
new
LockingObject
(
this
.readerWriterLock,accessMode);
}
}
///
<summary>
///
AccessMode訪問(wèn)鎖定資源的方式。
///
</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 附加:
我們都知道,對(duì)于集合類,如Lits<>,Dictionary<,>等,
(1)如果其它線程在對(duì)其中的元素進(jìn)行修改(如添加或刪除元素)時(shí),正在對(duì)集合進(jìn)行 枚舉 的線程會(huì)拋出異常。
(2)如果有一個(gè)線程正在對(duì)集合進(jìn)行修改,另外一個(gè)線程調(diào)用Contains/ContainsKey,會(huì)拋出異常嗎?答案是 不會(huì) 。
更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號(hào)聯(lián)系: 360901061
您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長(zhǎng)非常感激您!手機(jī)微信長(zhǎng)按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對(duì)您有幫助就好】元
