資源描述:
《C#多線程編程實(shí)例實(shí)戰(zhàn)》由會(huì)員上傳分享,免費(fèi)在線閱讀,更多相關(guān)內(nèi)容在工程資料-天天文庫(kù)。
1、C#多線程編程實(shí)例實(shí)戰(zhàn)C#多線程編程實(shí)例實(shí)戰(zhàn)2008-12-15問(wèn)題的提出所謂單個(gè)寫(xiě)入程序/多個(gè)閱讀程序的線程同步問(wèn)題,是指任意數(shù)量的線程訪問(wèn)共享資源時(shí),寫(xiě)入程序(線程)需要修改共享資源,而閱讀程序(線程)需要讀取數(shù)據(jù)。在這個(gè)同步問(wèn)題中,很容易得到下面二個(gè)要求:1)當(dāng)一個(gè)線程正在寫(xiě)入數(shù)據(jù)時(shí),其他線程不能寫(xiě),也不能讀。2)當(dāng)一個(gè)線程正在讀入數(shù)據(jù)時(shí),其他線程不能寫(xiě),但能夠讀。在數(shù)據(jù)庫(kù)應(yīng)用程序環(huán)境中經(jīng)常遇到這樣的問(wèn)題。比如說(shuō),有n個(gè)最終用戶,他們都要同時(shí)訪問(wèn)同一個(gè)數(shù)據(jù)庫(kù)。其中有m個(gè)用戶要將數(shù)據(jù)存入數(shù)據(jù)庫(kù),n-m個(gè)用戶要讀取數(shù)據(jù)庫(kù)中的記錄。很顯然,在這個(gè)環(huán)境中,我
2、們不能讓兩個(gè)或兩個(gè)以上的用戶同時(shí)更新同一條記錄,如果兩個(gè)或兩個(gè)以上的用戶都試圖同時(shí)修改同一記錄,那么該記錄中的信息就會(huì)被破壞。我們也不讓一個(gè)用戶更新數(shù)據(jù)庫(kù)記錄的同時(shí),讓另一用戶讀取記錄的內(nèi)容。因?yàn)樽x取的記錄很有可能同時(shí)包含了更新和沒(méi)有更新的信息,也就是說(shuō)這條記錄是無(wú)效的記錄。實(shí)現(xiàn)分析規(guī)定任一線程要對(duì)資源進(jìn)行寫(xiě)或讀操作前必須申請(qǐng)鎖。根據(jù)操作的不同,分為閱讀鎖和寫(xiě)入鎖,操作完成之后應(yīng)釋放相應(yīng)的鎖。將單個(gè)寫(xiě)入程序/多個(gè)閱讀程序的要求改變一下,可以得到如下的形式:一個(gè)線程申請(qǐng)閱讀鎖的成功條件是:當(dāng)前沒(méi)有活動(dòng)的寫(xiě)入線程。一個(gè)線程申請(qǐng)寫(xiě)入鎖的成功條件是:當(dāng)前沒(méi)有任何活
3、動(dòng)(對(duì)鎖而言)的線程。因此,為了標(biāo)志是否有活動(dòng)的線程,以及是寫(xiě)入還是閱讀線程,引入一個(gè)變量m_nActive,如果m_nActive>0,則表示當(dāng)前活動(dòng)閱讀線程的數(shù)目,如果m_nActive=0,則表示沒(méi)有任何活動(dòng)線程,m_nActive<0,表示當(dāng)前有寫(xiě)入線程在活動(dòng),注意m_nActive<0,時(shí)只能取-1的值,因?yàn)橹辉试S有一個(gè)寫(xiě)入線程活動(dòng)。為了判斷當(dāng)前活動(dòng)線程擁有的鎖的類(lèi)型,我們采用了線程局部存儲(chǔ)技術(shù)(請(qǐng)參閱其它參考書(shū)籍),將線程與特殊標(biāo)志位關(guān)聯(lián)起來(lái)。申請(qǐng)閱讀鎖的函數(shù)原型為:publicvoidAcquireReaderLock(intmillisec
4、ondsTimeout),其中的參數(shù)為線程等待調(diào)度的時(shí)間。函數(shù)定義如下:publicvoidAcquireReaderLock(intmillisecondsTimeout){//m_mutext很快可以得到,以便進(jìn)入臨界區(qū)m_mutex.WaitOne();//是否有寫(xiě)入線程存在boolbExistingWriter=(m_nActive<0);if(bExistingWriter){//等待閱讀線程數(shù)目加1,當(dāng)有鎖釋放時(shí),根據(jù)此數(shù)目來(lái)調(diào)度線程m_nWaitingReaders++;}else{//當(dāng)前活動(dòng)線程加1m_nActive++;}m_mutex
5、.ReleaseMutex();//存儲(chǔ)鎖標(biāo)志為ReaderSystem.LocalDataStoreSlotslot=Thread.GetNamedDataSlot(m_strThreadSlotName);objectobj=Thread.GetData(slot);LockFlagsflag=LockFlags.None;if(obj!=null)flag=(LockFlags)obj;if(flag==LockFlags.None){Thread.SetData(slot,LockFlags.Reader);}else{Thread.SetData
6、(slot,(LockFlags)((int)flag
7、(int)LockFlags.Reader));}if(bExistingWriter){//等待指定的時(shí)間this.m_aeReaders.WaitOne(millisecondsTimeout,true);}}它首先進(jìn)入臨界區(qū)(用以在多線程環(huán)境下保證活動(dòng)線程數(shù)目的操作的正確性)判斷當(dāng)前活動(dòng)線程的數(shù)目,如果有寫(xiě)線程(m_nActive<0)存在,則等待指定的時(shí)間并且等待的閱讀線程數(shù)目加1。如果當(dāng)前活動(dòng)線程是讀線程(m_nActive>=0),則可以讓讀線程繼續(xù)運(yùn)行。申請(qǐng)寫(xiě)入鎖的函數(shù)原型為:publi
8、cvoidAcquireWriterLock(intmillisecondsTimeout),其中的參數(shù)為等待調(diào)度的時(shí)間。函數(shù)定義如下:publicvoidAcquireWriterLock(intmillisecondsTimeout){//m_mutext很快可以得到,以便進(jìn)入臨界區(qū)m_mutex.WaitOne();//是否有活動(dòng)線程存在boolbNoActive=m_nActive==0;if(!bNoActive){m_nWaitingWriters++;}else{m_nActive--;}m_mutex.ReleaseMutex();//存儲(chǔ)
9、線程鎖標(biāo)志System.LocalDataStoreSlotslo