C#多线程编程实例实战

时间:2021-07-14 18:12 作者:乐鱼官网
本文摘要:C#多线程程序编写案例空中格斗单独载入程序流程/好几个阅读程序在.Net类库中只不过是早就获得了搭建,即System.Threading.ReaderWriterLock类。文中根据对罕见的单独载入/好几个阅读程序的剖析来探索c#的多线程程序编写。 难题的明确指出说白了单独载入程序流程/好几个阅读程序的线程即时难题,就是指给出总数的线程访问共享資源时,载入程序流程(线程)务必修改资源共享,而阅读程序(线程)务必获取数据。

乐鱼官网

C#多线程程序编写案例空中格斗单独载入程序流程/好几个阅读程序在.Net类库中只不过是早就获得了搭建,即System.Threading.ReaderWriterLock类。文中根据对罕见的单独载入/好几个阅读程序的剖析来探索c#的多线程程序编写。

难题的明确指出说白了单独载入程序流程/好几个阅读程序的线程即时难题,就是指给出总数的线程访问共享資源时,载入程序流程(线程)务必修改资源共享,而阅读程序(线程)务必获取数据。在这个即时难题中,很更非常容易得到 下边二个回绝:1)当一个线程已经载入数据信息时,别的线程没法写成,也没法阅读。2)当一个线程已经获取数据时,别的线程没法写成,但必须阅读。

1/21在数据库查询应用软件自然环境中经常遇到那样的难题。例如,有n个终端用户,她们必须另外访谈同一个数据库查询。在其中有m个客户要将数据信息现钱数据库查询,n-m个客户要载入数据库查询中的纪录。很好像,在这个自然环境中,我们无法让2个或2个之上的客户另外重做同一条纪录,假如2个或2个之上的客户都妄图另外修改同一纪录,那麼该纪录中的信息内容就不容易被损坏。

大家也不愿一个客户重做数据库查询纪录的另外,让另一客户载入纪录的內容。由于载入的纪录很有可能另外包含了重做和没重做的信息内容,换句话说这条纪录是违宪的纪录。2/21搭建剖析要求任一线程要对資源进行写成或阅读操作过程必不可少申报人锁住。

依据作业者的各有不同,分为读者锁住和载入锁住,作业者顺利完成以后不可出狱适度的锁住。将单独载入程序流程/好几个阅读程序的回绝变化一下,能够得到 以下的方式:一个线程申报人读者锁住的成功标准是:当今没主题活动的载入线程。一个线程申报人载入锁住的成功标准是:当今没一切主题活动(对锁住来讲)的线程。

3/21因而,为了更好地标示否有主题活动的线程,及其是载入還是读者线程,引入一个自变量m_nActive,假如m_nActive0,则答复当今主题活动读者线程的数量,假如m_nActive=0,则答复没一切主题活动线程,m_nActive0,答复当今有载入线程在主题活动,注意m_nActive0,时不可以所取-1的值,由于只允许有一个载入线程主题活动。为了更好地鉴别当今主题活动线程具有的锁住的种类,大家应用了线程部分存储系统(客户程序其他参考书本),将线程与相近标志位关系一起。4/21申报人读者锁住的函数原型为:publicvoidAcquireReaderLock(intmillisecondsTimeout),在其中的主要参数为线程等候生产调度的時间。

函数定义以下:publicvoidAcquireReaderLock(intmillisecondsTimeout){//m_mutext快速能够得到 ,便于转到临界区m_mutex.WaitOne();//否有载入线程不会有boolbExistingWriter=(m_nActive0);if(bExistingWriter){//等候读者线程数量特1,当有锁出狱时,依据此数量来生产调度线程m_nWaitingReaders ;}5/21else{//当今主题活动线程特1米_nActive ;}m_mutex.ReleaseMutex();//储存锁住标示为ReaderSystem.LocalDataStoreSlotslot=Thread.GetNamedDataSlot(m_strThreadSlotName);objectobj=Thread.GetData(slot);LockFlagsflag=LockFlags.None;if(obj!=null)flag=(LockFlags)obj;6/21if(flag==LockFlags.None){Thread.SetData(slot,LockFlags.Reader);}else{Thread.SetData(slot,(LockFlags)((int)flag|(int)LockFlags.Reader));}if(bExistingWriter){//等候登陆的時间this.m_aeReaders.WaitOne(millisecondsTimeout,true);}}它最先转到临界区(进而在多线程自然环境下保证 主题活动线程数量的作业者的准确性)鉴别当今主题活动线程的数量,如果有写成线程(m_nActive0)不会有,则等候登陆的時间而且等候的读者线程数量特1。假如当今主题活动线程是阅读线程(m_nActive=0),则能够让阅读线程以后经营。7/21申报人载入锁住的函数原型为:publicvoidAcquireWriterLock(intmillisecondsTimeout),在其中的主要参数为等候生产调度的時间。

函数定义以下:publicvoidAcquireWriterLock(intmillisecondsTimeout){//m_mutext快速能够得到 ,便于转到临界区m_mutex.WaitOne();//否有主题活动线程不会有boolbNoActive=m_nActive==0;if(!bNoActive){m_nWaitingWriters ;}else{m_nActive--;}8/21m_mutex.ReleaseMutex();//储存线程锁住标示System.LocalDataStoreSlotslot=Thread.GetNamedDataSlot(myReaderWriterLockDataSlot);objectobj=Thread.GetData(slot);LockFlagsflag=LockFlags.None;if(obj!=null)flag=(LockFlags)Thread.GetData(slot);if(flag==LockFlags.None){Thread.SetData(slot,LockFlags.Writer);}else{Thread.SetData(slot,(LockFlags)((int)flag|(int)LockFlags.Writer));}9/21//如果有主题活动线程,等候登陆的時间if(!bNoActive)this.m_aeWriters.WaitOne(millisecondsTimeout,true);}它最先转到临界区鉴别当今主题活动线程的数量,假如当今有主题活动线程不会有,无论是写成线程還是阅读线程(m_nActive),线程将等候登陆的時间而且等候的载入线程数量特1,不然线程具有写成的管理权限。10/21出狱读者锁住的函数原型为:publicvoidReleaseReaderLock()。

函数定义以下:publicvoidReleaseReaderLock(){System.LocalDataStoreSlotslot=Thread.GetNamedDataSlot(m_strThreadSlotName);LockFlagsflag=(LockFlags)Thread.GetData(slot);if(flag==LockFlags.None){return;}boolbReader=true;11/21switch(flag){caseLockFlags.None:break;caseLockFlags.Writer:bReader=false;break;}if(!bReader)return;Thread.SetData(slot,LockFlags.None);m_mutex.WaitOne();AutoResetEventautoresetevent=null;this.m_nActive--;12/21if(this.m_nActive==0){if(this.m_nWaitingReaders0){m_nActive ;m_nWaitingReaders--;autoresetevent=this.m_aeReaders;}13/21elseif(this.m_nWaitingWriters0){m_nWaitingWriters--;m_nActive--;autoresetevent=this.m_aeWriters;}}m_mutex.ReleaseMutex();if(autoresetevent!=null)autoresetevent.Set();}14/21出狱读者锁住时,最先鉴别当今线程否具有读者锁住(根据线程部分储存的标示),随后鉴别否有等候的读者线程,如果有,再作将当今主题活动线程特1,等候读者线程数量递减1,随后改置恶性事件为有数据信号。假如没等候的读者线程,鉴别否有等候的载入线程,如果有则主题活动线程数量递减1,等候的载入线程数量递减1。

出狱载入锁住与出狱读者锁住的全过程基本相同,能够参照源码。注意在程序流程中,出狱锁住时,只不容易清醒一个阅读程序,这是由于用以AutoResetEvent的原历,读者可自主将其改成ManualResetEvent,另外清醒好几个阅读程序,这时应令m_nActive相同全部等候的读者线程数量。15/21申报人载入锁住的函数原型为:publicvoidAcquireWriterLock(intmillisecondsTimeout),在其中的主要参数为等候生产调度的時间。函数定义以下:publicvoidAcquireWriterLock(intmillisecondsTimeout){//m_mutext快速能够得到 ,便于转到临界区m_mutex.WaitOne();//否有主题活动线程不会有boolbNoActive=m_nActive==0;if(!bNoActive){m_nWaitingWriters ;}else{m_nActive--;}16/21m_mutex.ReleaseMutex();//储存线程锁住标示System.LocalDataStoreSlotslot=Thread.GetNamedDataSlot(myReaderWriterLockDataSlot);objectobj=Thread.GetData(slot);LockFlagsflag=LockFlags.None;if(obj!=null)flag=(LockFlags)Thread.GetData(slot);if(flag==LockFlags.None){Thread.SetData(slot,LockFlags.Writer);}else{Thread.SetData(slot,(LockFlags)((int)flag|(int)LockFlags.Writer));}17/21//如果有主题活动线程,等候登陆的時间if(!bNoActive)this.m_aeWriters.WaitOne(millisecondsTimeout,true);}它最先转到临界区鉴别当今主题活动线程的数量,假如当今有主题活动线程不会有,无论是写成线程還是阅读线程(m_nActive),线程将等候登陆的時间而且等候的载入线程数量特1,不然线程具有写成的管理权限。

18/21出狱读者锁住的函数原型为:publicvoidReleaseReaderLock()。函数定义以下:publicvoidReleaseReaderLock(){System.LocalDataStoreSlotslot=Thread.GetNamedDataSlot(m_strThreadSlotName);LockFlagsflag=(LockFlags)Thread.GetData(slot);if(flag==LockFlags.None){return;}boolbReader=true;19/21switch(flag){caseLockFlags.None:break;caseLockFlags.Writer:bReader=false;break;}if(!bReader)return;Thread.SetData(slot,LockFlags.None);m_mutex.WaitOne();AutoResetEventautoresetevent=null;this.m_nActive--;20/21if(this.m_nActive==0){if(this.m_nWaiti ngReaders0){m_nActive ;m_nWaitingReaders--;autoresetevent=this.m_aeReaders;}elseif(this.m_nWaitingWriters0){m_nWaitingWriters--;m_nActive--;autoresetevent=this.m_aeWriters;}}21/21m_mutex.ReleaseMutex();if(autoresetevent!=null)autoresetevent.Set();}获释读者锁住时,最先鉴别当今线程否具有读者锁住(根据线程部分储存的标示),随后鉴别否有等候的读者线程,如果有,再作将当今主题活动线程特1,等候读者线程数目递减1,随后改置恶性事件为有数据信号。

假如没等候的读者线程,鉴别否有等候的加载线程,如果有则主题活动线程数目递减1,等候的加载线程数目递减1。获释加载锁住与获释读者锁住的全过程基本相同,能够参照源码。注意在程序流程中,获释锁住时,只不容易清醒一个阅读程序,这是由于用以AutoResetEvent的原历,读者可自主将其改成ManualResetEvent,另外清醒好几个阅读程序,这时应令m_nActive相同全部等候的读者线程数目。


本文关键词:多,线程,编程,实例,实战,多,线程,程序,编写,乐鱼体育

本文来源:乐鱼官网-www.maswes.com