知识大全 C#多线程编程实例
Posted 知
篇首语:读书忌死读,死读钻牛角。本文由小常识网(cha138.com)小编为大家整理,主要介绍了知识大全 C#多线程编程实例相关的知识,希望对你有一定的参考价值。
C#多线程编程实例 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!
问题的提出
所谓单个写入程序/多个阅读程序的线程同步问题 是指任意数量的线程访问共享资源时 写入程序(线程)需要修改共享资源 而阅读程序(线程)需要读取数据 在这个同步问题中 很容易得到下面二个要求
)当一个线程正在写入数据时 其他线程不能写 也不能读
)当一个线程正在读入数据时 其他线程不能写 但能够读
在数据库应用程序环境中经常遇到这样的问题 比如说 有n个最终用户 他们都要同时访问同一个数据库 其中有m个用户要将数据存入数据库 n m个用户要读取数据库中的记录
很显然 在这个环境中 我们不能让两个或两个以上的用户同时更新同一条记录 如果两个或两个以上的用户都试图同时修改同一记录 那么该记录中的信息就会被破坏
我们也不让一个用户更新数据库记录的同时 让另一用户读取记录的内容 因为读取的记录很有可能同时包含了更新和没有更新的信息 也就是说这条记录是无效的记录
实现分析
规定任一线程要对资源进行写或读操作前必须申请锁 根据操作的不同 分为阅读锁和写入锁 操作完成之后应释放相应的锁 将单个写入程序/多个阅读程序的要求改变一下 可以得到如下的形式
一个线程申请阅读锁的成功条件是 当前没有活动的写入线程
一个线程申请写入锁的成功条件是 当前没有任何活动(对锁而言)的线程
因此 为了标志是否有活动的线程 以及是写入还是阅读线程 引入一个变量m_nActive 如果m_nActive > 则表示当前活动阅读线程的数目 如果m_nActive= 则表示没有任何活动线程 m_nActive < 表示当前有写入线程在活动 注意m_nActive< 时只能取 的值 因为只允许有一个写入线程活动
为了判断当前活动线程拥有的锁的类型 我们采用了线程局部存储技术(请参阅其它参考书籍) 将线程与特殊标志位关联起来
申请阅读锁的函数原型为 public void AcquireReaderLock( int millisecondsTimeout ) 其中的参数为线程等待调度的时间 函数定义如下
public void AcquireReaderLock( int millisecondsTimeout ) // m_mutext很快可以得到 以便进入临界区 m_mutex WaitOne( ); // 是否有写入线程存在 bool bExistingWriter = ( m_nActive < ); if( bExistingWriter ) //等待阅读线程数目加 当有锁释放时 根据此数目来调度线程 m_nWaitingReaders++; else //当前活动线程加 m_nActive++; m_mutex ReleaseMutex(); //存储锁标志为Reader System LocalDataStoreSlot slot = Thread GetNamedDataSlot(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 ); else Thread SetData( slot (LockFlags)((int)flag | (int)LockFlags Reader ) ); if( bExistingWriter ) //等待指定的时间 this m_aeReaders WaitOne( millisecondsTimeout true );
它首先进入临界区(用以在多线程环境下保证活动线程数目的操作的正确性)判断当前活动线程的数目 如果有写线程(m_nActive< )存在 则等待指定的时间并且等待的阅读线程数目加 如果当前活动线程是读线程(m_nActive>= ) 则可以让读线程继续运行
申请写入锁的函数原型为 public void AcquireWriterLock( int millisecondsTimeout ) 其中的参数为等待调度的时间 函数定义如下
public void AcquireWriterLock( int millisecondsTimeout ) // m_mutext很快可以得到 以便进入临界区 m_mutex WaitOne( ); // 是否有活动线程存在 bool bNoActive = m_nActive == ; if( !bNoActive ) m_nWaitingWriters++; else m_nActive ; m_mutex ReleaseMutex(); //存储线程锁标志 System LocalDataStoreSlot slot = Thread GetNamedDataSlot( myReaderWriterLockDataSlot ); object obj = Thread GetData( slot ); LockFlags flag = 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 ) ); //如果有活动线程 等待指定的时间 if( !bNoActive ) this m_aeWriters WaitOne( millisecondsTimeout true );
它首先进入临界区判断当前活动线程的数目 如果当前有活动线程存在 不管是写线程还是读线程(m_nActive) 线程将等待指定的时间并且等待的写入线程数目加 否则线程拥有写的权限
释放阅读锁的函数原型为 public void ReleaseReaderLock() 函数定义如下
public void ReleaseReaderLock() System LocalDataStoreSlot slot = Thread GetNamedDataSlot(m_strThreadSlotName ); LockFlags flag = (LockFlags)Thread GetData( slot ); if( 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 == ) if( this m_nWaitingReaders > ) m_nActive ++ ; m_nWaitingReaders ; autoresetevent = this m_aeReaders; else if( this m_nWaitingWriters > ) m_nWaitingWriters ; m_nActive ; autoresetevent = this m_aeWriters ; m_mutex ReleaseMutex(); if( autoresetevent != null ) autoresetevent Set();
释放阅读锁时 首先判断当前线程是否拥有阅读锁(通过线程局部存储的标志) 然后判断是否有等待的阅读线程 如果有 先将当前活动线程加 等待阅读线程数目减 然后置事件为有信号 如果没有等待的阅读线程 判断是否有等待的写入线程 如果有则活动线程数目减 等待的写入线程数目减 释放写入锁与释放阅读锁的过程基本一致 可以参看源代码
注意在程序中 释放锁时 只会唤醒一个阅读程序 这是因为使用AutoResetEvent的原历 读者可自行将其改成ManualResetEvent 同时唤醒多个阅读程序 此时应令m_nActive等于整个等待的阅读线程数目
测试
测试程序取自 Net FrameSDK中的一个例子 只是稍做修改 测试程序如下
cha138/Article/program/net/201311/12614
相关参考
使用C#的BitmapData编程实例 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧! 最近要转开
C#高级编程读写文本文件实例 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧! 理论上可以使用Fil
编程中使用C#的BitmapData实例 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧! 最近要转
知识大全 Visual C#中实现DB2数据库的编程实例[1]
VisualC#中实现DB2数据库的编程实例[1] 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!
知识大全 Visual C#中实现DB2数据库的编程实例[3]
VisualC#中实现DB2数据库的编程实例[3] 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!
知识大全 Visual C#中实现DB2数据库的编程实例[2]
VisualC#中实现DB2数据库的编程实例[2] 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!t
Java多线程编程基础之线程和多线程 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧! 随着计算机技
超线程多核心下Java多线程编程分析 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧! 一Java环
超线程多核心下Java多线程编程技术分析[4] 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!&nb
超线程多核心下Java多线程编程技术分析[3] 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!&nb