




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、C#多线程编程实例实战问题的提出所谓单个写入程序 /多个阅读程序的线程同步问题, 是指任意数量的线程访问共享资源 时,写入程序(线程)需要修改共享资源,而阅读程序(线程)需要读取数据。在这个同步 问题中,很容易得到下面二个要求:1)当一个线程正在写入数据时,其他线程不能写,也不能读。2)当一个线程正在读入数据时,其他线程不能写,但能够读。在数据库应用程序环境中经常遇到这样的问题。比如说,有 n 个最终用户,他们都要 同时访问同一个数据库。其中有 m 个用户要将数据存入数据库, n-m 个用户要读取数据库 中的记录。很显然,在这个环境中,我们不能让两个或两个以上的用户同时更新同一条记录,如 果两
2、个或两个以上的用户都试图同时修改同一记录,那么该记录中的信息就会被破坏。我们也不让一个用户更新数据库记录的同时,让另一用户读取记录的内容。因为读取 的记录很有可能同时包含了更新和没有更新的信息,也就是说这条记录是无效的记录。实现分析规定任一线程要对资源进行写或读操作前必须申请锁。根据操作的不同,分为阅读锁 和写入锁, 操作完成之后应释放相应的锁。将单个写入程序 /多个阅读程序的要求改变一下, 可以得到如下的形式:一个线程申请阅读锁的成功条件是:当前没有活动的写入线程。一个线程申请写入锁的成功条件是:当前没有任何活动(对锁而言)的线程。因此,为了标志是否有活动的线程,以及是写入还是阅读线程,引入
3、一个变量 m_nActive ,如果 m_nActive 0 ,则表示当前活动阅读线程的数目,如果 m_nActive=0 ,则 表示没有任何活动线程, m_nActive 0 ,表示当前有写入线程在活动,注意 m_nActive0 , 时只能取 -1 的值,因为只允许有一个写入线程活动。为了判断当前活动线程拥有的锁的类型,我们采用了线程局部存储技术(请参阅其它 参考书籍),将线程与特殊标志位关联起来。申请阅读锁的函数原型为: public void AcquireReaderLock( int millisecondsTimeout ) , 其中的参数为线程等待调度的时间。函数定义如下:pu
4、blic void AcquireReaderLock( int millisecondsTimeout )/ m_mutext 很快可以得到,以便进入临界区 m_mutex.WaitOne( );/ 是否有写入线程存在bool bExistingWriter = ( m_nActive 0 );if( bExistingWriter ) / 等待阅读线程数目加 1,当有锁释放时,根据此数目来调度线程 m_nWaitingReaders+;else / 当前活动线程加 1m_nActive+;m_mutex.ReleaseMutex();/存储锁标志为 ReaderSystem.LocalDa
5、taStoreSlot 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 );elseThread.SetData( slot, (LockFlags)(int)flag | (int)LockF
6、lags.Reader ) );if( bExistingWriter ) / 等待指定的时间this.m_aeReaders.WaitOne( millisecondsTimeout, true );它首先进入临界区(用以在多线程环境下保证活动线程数目的操作的正确性)判断当 前活动线程的数目,如果有写线程 (m_nActive=0) ,则可以让读线程继续运行。申请写入锁的函数原型为: public void AcquireWriterLock( int millisecondsTimeout ) ,其 中的参数为等待调度的时间。函数定义如下:public void AcquireWriter
7、Lock( int millisecondsTimeout )/ m_mutext 很快可以得到,以便进入临界区m_mutex.WaitOne( );/ 是否有活动线程存在bool bNoActive = m_nActive = 0;if( !bNoActive )m_nWaitingWriters+;elsem_nActive-;m_mutex.ReleaseMutex();/存储线程锁标志System.LocalDataStoreSlot slot = Thread.GetNamedDataSlot( myReaderWriterLockDataSlot ); object obj = T
8、hread.GetData( slot );LockFlags flag = LockFlags.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_aeWrit
9、ers.WaitOne( millisecondsTimeout, true );它首先进入临界区判断当前活动线程的数目,如果当前有活动线程存在,不管是写线 程还是读线程( m_nActive ),线程将等待指定的时间并且等待的写入线程数目加1,否则线程拥有写的权限。释放阅读锁的函数原型为:public void ReleaseReaderLock() 。函数定义如下:public void ReleaseReaderLock()System.LocalDataStoreSlot slot = Thread.GetNamedDataSlot(m_strThreadSlotName );Lock
10、Flags 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
11、;this.m_nActive -;if( this.m_nActive = 0 )if( this.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 ) autorese
12、tevent.Set();释放阅读锁时, 首先判断当前线程是否拥有阅读锁 (通过线程局部存储的标志) ,然后 判断是否有等待的阅读线程,如果有,先将当前活动线程加 1,等待阅读线程数目减 1,然 后置事件为有信号。 如果没有等待的阅读线程, 判断是否有等待的写入线程, 如果有则活动 线程数目减 1,等待的写入线程数目减 1。释放写入锁与释放阅读锁的过程基本一致,可以 参看源代码。注意在程序中,释放锁时,只会唤醒一个阅读程序,这是因为使用 AutoResetEvent 的 原历,读者可自行将其改成 ManualResetEvent ,同时唤醒多个阅读程序, 此时应令 m_nActive 等于整个
13、等待的阅读线程数目。测试测试程序取自 .Net FrameSDK 中的一个例子,只是稍做修改。测试程序如下,using System;using System.Threading;using MyThreading;class Resource myReaderWriterLock rwl = new myReaderWriterLock(); public void Read(Int32 threadNum) rwl.AcquireReaderLock(Timeout.Infinite);try Console.WriteLine(Start Resource reading (Thread
14、=0), 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(Start Resource writing (Thread=0), threadNum);Thread.Sleep(750);Console.W
15、riteLine(Stop Resource writing (Thread=0), threadNum); finally rwl.ReleaseWriterLock();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; thre
16、adNum+) ThreadPool.QueueUserWorkItem(new WaitCallback(UpdateResource), threadNum);asyncOpsAreDone.WaitOne();Console.WriteLine(All operations have completed.);Console.ReadLine();/ The callback methods signature MUST match that of a System.Threading.TimerCallback/ delegate (it takes an Object parameter and return
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 江苏省徐州市2024-2025学年高三下学期2月调研测试数学试卷(解析版)
- 内蒙古自治区赤峰市松山区2024-2025学年八年级上学期期末物理试题(原卷版+解析版)
- 4.3 探究熔化和凝固的特点 说课稿 2025年初中物理八年级上学期
- 年计生工作计划
- 园长学期工作计划
- 《深度学习项目案例开发》课件-任务三 使用数据增强抑制卷积神经网络过拟合
- 浙江省台州市温岭中学2024-2025学年高三下学期3月考试数学试题(原卷版+解析版)
- 《跨境电商》课件-8.产品优化操作
- 农产品质量追溯与物流一体化解决方案
- 建设工程施工分包委托协议书
- 2025年聚焦全国两会知识竞赛题库及答案(共100题)
- 2024智能网联汽车零部件行业研究报告-2025-01-智能网联
- 统计学专业大学生职业生涯发展
- 2025年中国融通资产管理集团限公司春季招聘(511人)高频重点提升(共500题)附带答案详解
- 急性心肌梗死的急救与护理
- GB/T 9755-2024合成树脂乳液墙面涂料
- T-CAMET 05002-2020 城市轨道交通隧道抗风压防火门工程技术规范
- 2024年人力资源和社会保障部公开招聘工作人员历年管理单位遴选500模拟题附带答案详解
- 文化地理学前沿理论-洞察分析
- 中国算力中心服务商分析报告(2024年)
- DB36T 1452-2021 城镇地理实体空间数据规范
评论
0/150
提交评论