您好,登錄后才能下訂單哦!
本篇內(nèi)容主要講解“.NET開發(fā)中多線程的使用”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實(shí)用性強(qiáng)。下面就讓小編來帶大家學(xué)習(xí)“.NET開發(fā)中多線程的使用”吧!
在NET中,我們用的最多的鎖機(jī)制就是lock,用起來很簡單,短短幾行程序就可以實(shí)現(xiàn),例如:
Lock 's Code public class TestThreading { private System.Object lockThis = new System.Object(); public void Function() { lock (lockThis) { // Access thread-sensitive resources. } } } |
其實(shí)我們也明白,lock并不是鎖,而是MS提供的一個(gè)簡便式的寫法,真正實(shí)現(xiàn)的是Monitor類中的Enter和Exit方法,既然提到了Monitor類也就說下有個(gè)需要注意的地方:
Pulse和PulseAll方法,這兩個(gè)方法就是把鎖狀態(tài)將要改變的消息通知給等待隊(duì)列中的線程,不過這時(shí)如果等待隊(duì)列中沒有線程,那么該方法就會(huì)一直等待下去,直到有等待的線程進(jìn)入隊(duì)列,也就是說該方法可能造成類試死鎖的情況出現(xiàn)。
上面的lock + 線程(Thread和ThreadPool) = 多線程編程(N%)???
對于該公式我曾經(jīng)的N是80,現(xiàn)在是20。其中有很多東西影響我,讓我從80->20,下面的Optex就是一個(gè)入口點(diǎn)。
--------------------------------------------------------------------------------
Optex 's Code
public sealed class Optex : IDisposable {
private Int32 m_Waiters = 0;
private Semaphore m_WaiterLock = new Semaphore(0, Int32.MaxValue);public Optex() { }
public void Dispose() {
if (m_WaiterLock != null)
{
m_WaiterLock.Close();
m_WaiterLock = null;
}
}public void Enter() {
Thread.BeginCriticalRegion();
// Add ourself to the set of threads interested in the Optex
if (Interlocked.Increment(ref m_Waiters) == 1) {
// If we were the first thread to show interest, we got it.
return;
}// Another thread has the Optex, we need to wait for it
m_WaiterLock.WaitOne();
// When WaitOne returns, this thread now has the Optex
}public void Exit() {
// Subtract ourself from the set of threads interested in the Optex
if (Interlocked.Decrement(ref m_Waiters) > 0) {
// Other threads are waiting, wake 1 of them
m_WaiterLock.Release(1);
}
Thread.EndCriticalRegion();
}
}
看完上面的代碼,讓我增加了兩點(diǎn)認(rèn)識(shí):
1、Thread.BeginCriticalRegion()和Thread.EndCriticalRegion();
因?yàn)檫@段時(shí)間正好看了一本多線程編程的書,既然將上面方法認(rèn)為是進(jìn)入臨界區(qū)和退出臨界區(qū),對于臨界區(qū)而言,進(jìn)入該區(qū)的數(shù)據(jù),在沒有退出之前,如果臨界區(qū)外的程序需要使用它,那么就必須出于等待。所以覺得已經(jīng)使用臨界區(qū),為什么還要使用Semaphore?!
可是,MS只是取了個(gè)相同的名字,做的事情完全不同,上面兩個(gè)方法完全沒有臨界區(qū)的概念,它只是設(shè)置一個(gè)區(qū)域(Begin到End之間),表示該區(qū)域內(nèi)發(fā)生線程中斷或未處理的異常會(huì)影響整個(gè)應(yīng)用程序域。
2、m_Waiters的作用
一開始以為在Enter的時(shí)候,直接寫上:
m_WaiterLock.WaitOne(); |
Exit的時(shí)候,寫上:
m_WaiterLock.Release(1); |
這樣就可以了。m_Waiters有什么意義?!
優(yōu)化性能,Semaphore是內(nèi)核對象,我們都知道,要盡量少的進(jìn)入內(nèi)核模式,因?yàn)檫@是很消耗性能,所以盡量少的使用內(nèi)核對象。m_Waiters的意義就在這里,如果只有一個(gè)線程使用該鎖對象的時(shí)候,是不需要去獲取和釋放的。 OK,上述的東西都是鋪墊,鋪完了也就進(jìn)入主題了!
多線程的思維
優(yōu)化的Optex
namespace ThreadConcurrent.Lock { public sealed class Optex : IDisposable { /// private Int32 m_LockState = c_lsFree; private const Int32 c_lsFree = 0x00000000; /// private const Int32 c_lsOwned = 0x00000001; /// private const Int32 c_1Waiter = 0x00000002; public Optex() { } public void Enter() { Thread.BeginCriticalRegion(); while (true) { Int32 ls = InterlockedOr(ref m_LockState, c_lsOwned); ///[object Object] ///[object Object] /// private static Int32 InterlockedAnd(ref Int32 target, Int32 with) { Int32 i, j = target; do { i = j; j = Interlocked.CompareExchange(ref target, i & with, i); } while (i != j); return j; } ///[object Object] ///[object Object] /// private static Int32 InterlockedOr(ref Int32 target, Int32 with) { Int32 i, j = target; do { i = j; j = Interlocked.CompareExchange(ref target, i | with, i); } while (i != j); return j; } public void Dispose() { if (m_WaiterLock != null) { m_WaiterLock.Close(); m_WaiterLock = null; } } } }
對于上面的這個(gè)代碼,我暈眩了好一段時(shí)間,不過當(dāng)我真正理解的時(shí)候,從暈眩中學(xué)到了做多線程編程應(yīng)該具備的思維方式。
首先從簡單的理解開始談,
1、原子化操作
對于InterLocked類,曾經(jīng)也知道,但是卻用的很少,不過從該代碼中知道,在多線程的編程中對共享數(shù)據(jù)的寫入操作,一定要達(dá)到原子性。至于如何做到這點(diǎn),InterlockedAnd和InterlockedOr做了很好的詮釋:
While循環(huán)的目的就是保證target值以***的值做與操作,如果傳入的值在執(zhí)行的過程被其他線程改變的話,那么是不會(huì)退出該循環(huán)的,并會(huì)利用改變后的值重新做次與操作。
2、理解Enter和Exit
這兩個(gè)方法很難寫出來解釋,用圖是最清晰的。
曾經(jīng)的暈眩:
1、Enter方法中為什么存在循環(huán),為什么不是執(zhí)行完waitone就結(jié)束,必須m_lockState等于c_IsFree的時(shí)候才結(jié)束?
線程的執(zhí)行并不完全按照先前排好的順序去執(zhí)行,有時(shí)會(huì)發(fā)生一些特殊的情況來使改變線程的調(diào)度順序,所以就可能會(huì)出現(xiàn)上圖灰色部分的情況,則為了解決該可能發(fā)生的問題(概率很?。┭h(huán)機(jī)制就出現(xiàn)了。
2、為什么在WaitOne和Release之前,除了增加和減少等待者外,還需要判斷m_lockstate是否改變(進(jìn)入Enter到執(zhí)行Waitone前的這段時(shí)間)?
一般性的思維:
該程序的思維:
這樣做的好處就是盡量少的操作內(nèi)核對象,提高性能!
多線程編程雖然復(fù)雜,但是我覺得很有意思和挑戰(zhàn)性,而且隨著硬件的發(fā)展,多線程編程會(huì)更加重要,既然已經(jīng)上路就讓我們走到盡頭!
到此,相信大家對“.NET開發(fā)中多線程的使用”有了更深的了解,不妨來實(shí)際操作一番吧!這里是億速云網(wǎng)站,更多相關(guān)內(nèi)容可以進(jìn)入相關(guān)頻道進(jìn)行查詢,關(guān)注我們,繼續(xù)學(xué)習(xí)!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。