C#多线程:使用ReaderWriterLock类实现多用户读/单用户写同步
- 摘要:C#提供了System.Threading.ReaderWriterLock类以适应多用户读/单用户写的场景。该类可实现以下功能:如果资源未被写操作锁定,那么任何线程都可对该资源进行读操作锁定,并且对读操作锁数量没有限制,即多个线程可同时对该资源进行读操作锁定,以读取数据。
使用Monitor或Mutex进行同步控制的问题:由于独占访问模型不允许任何形式的并发访问,这样的效率总是不太高。许多时候,应用程序在访问资源时是进行读操作,写操作相对较少。为解决这一问题,C#提供了System.Threading.ReaderWriterLock类以适应多用户读/单用户写的场景。该类可实现以下功能:如果资源未被写操作锁定,那么任何线程都可对该资源进行读操作锁定,并且对读操作锁数量没有限制,即多个线程可同时对该资源进行读操作锁定,以读取数据。如果资源未被添加任何读或写操作锁,那么一个且仅有一个线程可对该资源添加写操作锁定,以写入数据。简单的讲就是:读操作锁是共享锁,允许多个线程同时读取数据;写操作锁是独占锁,同一时刻,仅允许一个线程进行写操作。
示例代码如下:
using System;
using System.Threading; namespace ProcessTest
{
class Program
{
//资源
static int theResource = 0;
//读、写操作锁
static ReaderWriterLock rwl = new ReaderWriterLock(); static void Main(string[] args)
{
//分别创建2个读操作线程,2个写操作线程,并启动
Thread tr0 = new Thread(new ThreadStart(Read));
Thread tr1 = new Thread(new ThreadStart(Read));
Thread tr2 = new Thread(new ThreadStart(Write));
Thread tr3 = new Thread(new ThreadStart(Write)); tr0.Start();
tr1.Start();
tr2.Start();
tr3.Start(); //等待线程执行完毕
tr0.Join();
tr1.Join();
tr2.Join();
tr3.Join(); System.Console.ReadKey();
} //读数据
static void Read()
{
for (int i = 0; i < 3; i++)
{
try
{
//申请读操作锁,如果在1000ms内未获取读操作锁,则放弃
rwl.AcquireReaderLock(1000);
Console.WriteLine("开始读取数据,theResource = {0}", theResource);
Thread.Sleep(10);
Console.WriteLine("读取数据结束,theResource = {0}", theResource);
//释放读操作锁
rwl.ReleaseReaderLock();
}
catch (ApplicationException)
{
//获取读操作锁失败的处理
}
}
} //写数据
static void Write()
{
for (int i = 0; i < 3; i++)
{
try
{
//申请写操作锁,如果在1000ms内未获取写操作锁,则放弃
rwl.AcquireWriterLock(1000);
Console.WriteLine("开始写数据,theResource = {0}", theResource);
//将theResource加1
theResource++;
Thread.Sleep(100);
Console.WriteLine("写数据结束,theResource = {0}", theResource);
//释放写操作锁
rwl.ReleaseWriterLock();
}
catch (ApplicationException)
{
//获取写操作锁失败
}
}
}
}
}
上例中分别创建2个读取线程和2个写入线程,交替进行读、写操作。运行结果如下图:

观察运行结果,我们很容易看出:读操作锁是共享锁,允许多个线程同时读取数据;写操作锁是独占锁,仅允许一个线程进行写操作。
如果一个线程在获取读操作锁后,进行读操作的途中,希望提升锁级别,将其变为写操作锁,可以调用ReaderWriterLock类的UpgradeToWriterLock(int timeOut)方法,该方法返回一个LockCookie值,该值保存了UpgradeToWriterLock方法调用前线程锁的状态。待写操作完成后,可调用DowngradeFromWriterLock(LockCookie lockcookie)方法,该方法根据传入的LockCookie参数值,将线程锁恢复到UpgradeToWriterLock方法调用前的状态。具体使用方法,大家可以查看MSDN以获取相关示例。
C#多线程:使用ReaderWriterLock类实现多用户读/单用户写同步的更多相关文章
- 使用ReaderWriterLock类实现多用户读/单用户写同步
使用ReaderWriterLock类实现多用户读/单用户写同步[1] 2015-03-12 应用程序在访问资源时是进行读操作,写操作相对较少.为解决这一问题,C#提供了System.Threadin ...
- c++ 多个线程读一个线程写同步
这种情况一般多个线程读是不需要加锁的.就在写的时候需要加锁. 那么要做的就是让不写的时候,读不受同步限制.让多线程自由的读. 这个时候就要用读写锁 boost已经有读写锁,而c++ 14才有读写锁. ...
- SQLSERVER 切换数据库为单用户和多用户模式
有时候数据库在占用时,想做一些操作,无法操作.可以尝试将数据库切换为单用户模式来操作.操作完之后再切换回多用户模式. 命令如下: alter database 数据库名 set Single_user ...
- ReaderWriterLock类(转)
ReaderWriterLock类 通常来讲,一个类型的实例对于并行的读操作是线程安全的,但是并行地更新操作则不是(并 行地读和更新也不是). 这对于资源也是一样的,比如一个文件.当保护类型的实例安全 ...
- Java多线程01(Thread类、线程创建、线程池)
Java多线程(Thread类.线程创建.线程池) 第一章 多线程 1.1 多线程介绍 1.1.1 基本概念 进程:进程指正在运行的程序.确切的来说,当一个程序进入内存运行,即变成一个进程,进程是处于 ...
- PHP CURL 多线程 GET/POST 类
PHP CURL 多线程 GET/POST 类 2015-01-01 分类:技术文章 阅读(623) 评论(0) 如果有需要更正或更高效的建议,欢迎在OSchina分享~\(≧▽≦)/~ http:/ ...
- 【C/C++多线程编程之九】pthread读写锁
多线程编程之读写锁 Pthread是 POSIX threads 的简称,是POSIX的线程标准. pthread读写锁把对共享资源的訪问者分为读者和写者,读者仅仅对共享资源 ...
- Java多线程基础——Lock类
之前已经说道,JVM提供了synchronized关键字来实现对变量的同步访问以及用wait和notify来实现线程间通信.在jdk1.5以后,JAVA提供了Lock类来实现和synchronized ...
- (转)多线程——继承Thread 类和实现Runnable 接口的区别
java中我们想要实现多线程常用的有两种方法,继承Thread 类和实现Runnable 接口,有经验的程序员都会选择实现Runnable接口 ,其主要原因有以下两点: 首先,java只能单继承,因此 ...
随机推荐
- IOS-各控件默认尺寸和参考图标大小
UITabBar
- CCNA学习 NAT网络地址转换
CCNA基础 NAT网络地址转换 在计算机网络中,网络地址转换(Network Address Translation,缩写为NAT),也叫做网络掩蔽或者IP掩蔽(IP masquerading),是 ...
- replicate复制函数
按指定次数重复字符表达式 REPLICATE ( character_expression, integer_expression) character_expression 字符数据型的字母数字表达 ...
- SQL Server 2014云特性:无缝集成公有云
本篇是我在IT168的约稿,原文地址:http://tech.it168.com/a2014/0620/1637/000001637358_all.shtml IT行业已经进入了云时代,未 ...
- struts2拦截器
一.自定义拦截器 struts2拦截器类似于servlet过滤器 首先定义一个拦截器这个拦截器实现了Interceptor接口: package cn.orlion.interceptor; impo ...
- 邻接矩阵有向图(一)之 C语言详解
本章介绍邻接矩阵有向图.在"图的理论基础"中已经对图进行了理论介绍,这里就不再对图的概念进行重复说明了.和以往一样,本文会先给出C语言的实现:后续再分别给出C++和Java版本的实 ...
- MongoDB的学习--explain()和hint()
Explain 从之前的文章中,我们可以知道explain()能够提供大量与查询相关的信息.对于速度比较慢的查询来说,这是最重要的诊断工具之一.通过查看一个查询的explain()输出信息,可以知道查 ...
- PHP内核的学习--创建PHP扩展
开始看PHP内核也有一段时间了,现在开始边学边总结,今天就总结一下如何创建自己的PHP扩展. 我的环境如下: 系统:Ubuntu 14.04 php版本:5.5.19 参考摘录:用C/C++扩展你的P ...
- CSS 魔法系列:纯 CSS 绘制图形(各种形状的钻石)
我们的网页因为 CSS 而呈现千变万化的风格.这一看似简单的样式语言在使用中非常灵活,只要你发挥创意就能实现很多比人想象不到的效果.特别是随着 CSS3 的广泛使用,更多新奇的 CSS 作品涌现出来. ...
- TCP/IP详解学习笔记(13)-TCP坚持定时器,TCP保活定时器
TCP一共有四个主要的定时器,前面已经讲到了一个--超时定时器--是TCP里面最复杂的一个,另外的三个是: 坚持定时器 保活定时器 2MSL定时器 其中坚持定时器用于防止通告窗口为0以后双方互相等待死 ...