

下載本文檔
版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領
文檔簡介
1、C#多線程編程實例實戰問題的提出所謂單個寫入程序/多個閱讀程序的線程同步問題, 是指任意數量的線 程訪問共享資源時,寫入程序(線程)需要修改共享資源,而閱讀程序(線 程)需要讀取數據。在這個同步問題中,很容易得到下面二個要求:1) 當一個線程正在寫入數據時,其他線程不能寫,也不能讀。2) 當一個線程正在讀入數據時,其他線程不能寫,但能夠讀。 在數據庫應用程序環境中經常遇到這樣的問題。比如說,有n個最終用戶,他們都要同時訪問同一個數據庫。其中有m個用戶要將數據存入數據 庫,n-m個用戶要讀取數據庫中的記錄。很顯然,在這個環境中,我們不能讓兩個或兩個以上的用戶同時更新 同一條記錄,如果兩個或兩個以
2、上的用戶都試圖同時修改同一記錄,那么該 記錄中的信息就會被破壞。我們也不讓一個用戶更新數據庫記錄的同時,讓另一用戶讀取記錄的 內容。因為讀取的記錄很有可能同時包含了更新和沒有更新的信息,也就是 說這條記錄是無效的記錄。實現分析規定任一線程要對資源進行寫或讀操作前必須申請鎖。根據操作的不 同,分為閱讀鎖和寫入鎖,操作完成之后應釋放相應的鎖。將單個寫入程序/多個閱讀程序的要求改變一下,可以得到如下的形式:一個線程申請閱讀鎖的成功條件是:當前沒有活動的寫入線程。一個線程申請寫入鎖的成功條件是:當前沒有任何活動(對鎖而言)的線程因此,為了標志是否有活動的線程,以及是寫入還是閱讀線程,引入 一個變量m_
3、nActive,如果m_nActive 0,則表示當前活動閱讀線程的數 目,如果m_nActive=0,則表示沒有任何活動線程,m_nActive 0,表示當 前有寫入線程在活動,注意m_nActive0,時只能取-1的值,因為只允許有 一個寫入線程活動。為了判斷當前活動線程擁有的鎖的類型,我們采用了線程局部存儲技 術(請參閱其它參考書籍) ,將線程與特殊標志位關聯起來。申請閱讀鎖的函數原型為:public void AcquireReaderLock( intmillisecondsTimeout ),其中的參數為線程等待調度的時間。函數定義如 下:publicvoid AcquireRea
4、derLock( int millisecondsTimeout )/ m_mutext很快可以得到,以便進入臨界區m_mutex.WaitOne( );/是否有寫入線程存在bool bExistingWriter = ( m_nActive 0 );if( bExistingWriter ) /等待閱讀線程數目加1,當有鎖釋放時,根據此數目來調度線程m_nWaitingReaders+;else /當前活動線程加1 m_nActive+;m_mutex.ReleaseMutex();/存儲鎖標志為ReaderSystem.LocalDataStoreSlot slotThread.GetNa
5、medDataSlot(m_strThreadSlotName); object obj =Thread.GetData( slot );LockFlags flag = LockFlags.None;if( obj != null )flag = (LockFlags)obj ;if( flag = LockFlags.None )Thread.SetData( slot, LockFlags.Reader );elseThread.SetData( slot, (LockFlags)(int)flag | (int)LockFlags.Reader ) );if( bExistingWri
6、ter ) /等待指定的時間this.m_aeReaders.WaitOne( millisecondsTimeout, true );它首先進入臨界區(用以在多線程環境下保證活動線程數目的操作的 正確性)判斷當前活動線程的數目,如果有寫線程(m_nActive=0),則可以讓讀線程繼續運行。申請寫入鎖的函數原型為:public void AcquireWriterLock( intmillisecondsTimeout ),其中的參數為等待調度的時間。函數定義如下:public voidAcquireWriterLock( int millisecondsTimeout )/ m_mutex
7、t很快可以得到,以便進入臨界區m_mutex.WaitOne( );/是否有活動線程存在bool bNoActive = m_nActive = 0;if( !bNoActive )m_nWaitingWriters+;elsem_nActive-;m_mutex.ReleaseMutex();/存儲線程鎖標志System.LocalDataStoreSlot slotThread.GetNamedDataSlot( myReaderWriterLockDataSlot );object obj = Thread.GetData( slot );LockFlags flag = LockFla
8、gs.None;if( obj != null )flag = (LockFlags)Thread.GetData( slot );if( flag = LockFlags.None )Thread.SetData( slot, LockFlags.Writer );elseThread.SetData( slot, (LockFlags)(int)flag | (int)LockFlags.Writer ) );/如果有活動線程,等待指定的時間if( !bNoActive ) this.m_aeWriters.WaitOne( millisecondsTimeout, true );它首先進
9、入臨界區判斷當前活動線程的數目,如果當前有活動線程存 在,不管是寫線程還是讀線程(m_nActive),線程將等待指定的時間并且等 待的寫入線程數目加1,否則線程擁有寫的權限。釋放閱讀鎖的函數原型為:public void ReleaseReaderLock()。函數定義如下:public void ReleaseReaderLock()System.LocalDataStoreSlot slotThread.GetNamedDataSlot(m_strThreadSlotName );LockFlags flag = (LockFlags)Thread.GetData( slot );if(
10、 flag = LockFlags.None )return;bool bReader = true;switch( flag )case LockFlags.None:break;case LockFlags.Writer: bReader = false;break;if( !bReader ) return;Thread.SetData( slot, LockFlags.None ); m_mutex.WaitOne();AutoResetEvent autoresetevent = null; this.m_nActive -;if( this.m_nActive = 0 )if( t
11、his.m_nWaitingReaders 0 )m_nActive + ;m_nWaitingReaders -; autoresetevent = this.m_aeReaders;else if( this.m_nWaitingWriters 0)m_nWaitingWriters-; m_nActive -;autoresetevent = this.m_aeWriters ;m_mutex.ReleaseMutex();if( autoresetevent != null )autoresetevent.Set();釋放閱讀鎖時,首先判斷當前線程是否擁有閱讀鎖(通過線程局部存 儲的標
12、志),然后判斷是否有等待的閱讀線程,如果有,先將當前活動線程 加1,等待閱讀線程數目減1,然后置事件為有信號。如果沒有等待的閱讀 線程,判斷是否有等待的寫入線程,如果有則活動線程數目減1,等待的寫入線程數目減1。釋放寫入鎖與釋放閱讀鎖的過程基本一致,可以參看源代 碼。注意在程序中,釋放鎖時,只會喚醒一個閱讀程序,這是因為使用AutoResetEvent的原歷,讀者可自行將其改成ManualResetEvent,同時喚 醒多個閱讀程序,此時應令m_nActive等于整個等待的閱讀線程數目。 測試測試程序取自.Net FrameSDI中的一個例子,只是稍做修改。測試程序如下,using Syste
13、m;using System.Threading;using MyThreading;class Resource myReaderWriterLock rwl = new myReaderWriterLock();public void Read(Int32 threadNum) rwl.AcquireReaderLock(Timeout.Infinite);try threadNum);Thread.Sleep(750);Console.WriteLine(Stop Resource writingfinally rwl.ReleaseWriterLock();Console.WriteL
14、ine(StartResourcereading(Thread=threadNum);Thread.Sleep(250);Console.WriteLine(Stop Resource reading(Thread=0), threadNum);finally rwl.ReleaseReaderLock();public void Write(Int32 threadNum) rwl.AcquireWriterLock(Timeout.Infinite);try Console.WriteLine(StartResourcewriting(Thread=(Thread=0), threadNu
15、m);class App static Int32 numAsyncOps = 20;static AutoResetEvent asyncOpsAreDone = new AutoResetEvent(false);static Resource res = new Resource();public static void Main() for (Int32 threadNum = 0; threadNum 20; threadNum+) ThreadPool.QueueUserWorkItem(new WaitCallback(UpdateResource),threadNum);asyncOpsAreDone.WaitOne();Console.WriteLine(All operations have completed.);Console.ReadLine();/ delegate (it takes an Object parameter and returns void)stati
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經權益所有人同意不得將文件中的內容挪作商業或盈利用途。
- 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
- 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 模具設計師資格認證考試萬無一失試題及答案
- 2024年農作物種子繁育員考試的閉卷復習試題及答案
- 2024模具設計師考試模擬試題及答案
- 2024年農業植保員考試解析與試題及答案
- 準備2024年游泳救生員考試的資料與試題及答案
- 2024年體育經紀人考試工具手冊試題及答案
- 2024年職業能力測試體育經紀人試題及答案
- 深入分析農作物種子供給鏈的試題及答案
- 2024年游泳救生員考試的有用工具試題及答案
- 游泳救生員水域安全規范與管理試題及答案
- 煤礦標準成本消耗定額(定額裝訂版)
- 《騎鵝旅行記》閱讀題(有答案,內容全)
- 【越南】環境保護法
- 《C語言程序設計》教案(清華譚浩強)
- ●粘度對離心泵性能影響最新標準初析及粘液泵選型經驗
- 環己烷安全周知卡-原料
- 三寶證盟薦亡往生功德文疏
- YY∕T 1849-2022 重組膠原蛋白
- 行政管理工作流程優化方案
- 鼓式制動器畢業設計
- 醫院內部醫療廢物收集運送流程圖
評論
0/150
提交評論