• 摘要: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类实现多用户读/单用户写同步的更多相关文章

  1. 使用ReaderWriterLock类实现多用户读/单用户写同步

    使用ReaderWriterLock类实现多用户读/单用户写同步[1] 2015-03-12 应用程序在访问资源时是进行读操作,写操作相对较少.为解决这一问题,C#提供了System.Threadin ...

  2. c++ 多个线程读一个线程写同步

    这种情况一般多个线程读是不需要加锁的.就在写的时候需要加锁. 那么要做的就是让不写的时候,读不受同步限制.让多线程自由的读. 这个时候就要用读写锁 boost已经有读写锁,而c++ 14才有读写锁. ...

  3. SQLSERVER 切换数据库为单用户和多用户模式

    有时候数据库在占用时,想做一些操作,无法操作.可以尝试将数据库切换为单用户模式来操作.操作完之后再切换回多用户模式. 命令如下: alter database 数据库名 set Single_user ...

  4. ReaderWriterLock类(转)

    ReaderWriterLock类 通常来讲,一个类型的实例对于并行的读操作是线程安全的,但是并行地更新操作则不是(并 行地读和更新也不是). 这对于资源也是一样的,比如一个文件.当保护类型的实例安全 ...

  5. Java多线程01(Thread类、线程创建、线程池)

    Java多线程(Thread类.线程创建.线程池) 第一章 多线程 1.1 多线程介绍 1.1.1 基本概念 进程:进程指正在运行的程序.确切的来说,当一个程序进入内存运行,即变成一个进程,进程是处于 ...

  6. PHP CURL 多线程 GET/POST 类

    PHP CURL 多线程 GET/POST 类 2015-01-01 分类:技术文章 阅读(623) 评论(0) 如果有需要更正或更高效的建议,欢迎在OSchina分享~\(≧▽≦)/~ http:/ ...

  7. 【C/C++多线程编程之九】pthread读写锁

    多线程编程之读写锁      Pthread是 POSIX threads 的简称,是POSIX的线程标准.         pthread读写锁把对共享资源的訪问者分为读者和写者,读者仅仅对共享资源 ...

  8. Java多线程基础——Lock类

    之前已经说道,JVM提供了synchronized关键字来实现对变量的同步访问以及用wait和notify来实现线程间通信.在jdk1.5以后,JAVA提供了Lock类来实现和synchronized ...

  9. (转)多线程——继承Thread 类和实现Runnable 接口的区别

    java中我们想要实现多线程常用的有两种方法,继承Thread 类和实现Runnable 接口,有经验的程序员都会选择实现Runnable接口 ,其主要原因有以下两点: 首先,java只能单继承,因此 ...

随机推荐

  1. Enterprise Solution 界面设计规范

    Enteprise Solution有一套自己的界面设计规范,也是很多年(10年以上)管理软件界面精华的积累.没有一个软件从一开始就很善于界面设计,许多个小小的改善,比如控件位置的移动,控件摆放顺序的 ...

  2. JS面向对象逆向学习法,让难理解的统统一边去(1)~

    对于面向对象我只能说呵呵了,为什么呢,因为没对象--- 既然你看到了这里,说明你有一定的基础,虽然本系列文章并不会过多的讲述基础部分,请做好心理准备. 本篇比较简单,这篇文章的意义是让你明白学习面向对 ...

  3. SVN更改登录用户

    如果装了TortoiseSVN: Settings -> Saved Data -> Authentication Data -> clear.即可清除保存的上个用户登录信息:当再次 ...

  4. android 手机开启debug日志

    来自 http://blog.csdn.net/aikongmeng/article/details/9764297 真机默认是不开启Log 开关的,这么来说我们如果使用真机来搞程序测试的话,需要做以 ...

  5. java 模拟qq源码

    java 模拟qq源码: http://files.cnblogs.com/files/hujunzheng/QQ--hjzgg.zip

  6. java中泛型上限,下限应用

    v 一.程序中无形之中用到的泛型 import java.util.*; class Person implements Comparable<Person>{ String name; ...

  7. 如何配置Hyper-V的虚拟机通过主机网络上网 (NAT)

    前言 最近开始在Windows 8 上面直接使用Hyper-V的技术来建立虚拟环境进行开发和测试,这样免去了再安装额外软件的需要.在实际使用的时候,尤其是配置网络共享的时候,遇到些问题,与其他一些虚拟 ...

  8. MySQL5.6忘记root密码(win平台)

    1.首先net stop mysql服务,并且切换到任务管理器,有与mysql有关的,最好关闭进程. 2.运行CMD命令切换到MySql安装bin目录,下面是我的mysql安装目录 cd  C:\Pr ...

  9. [New Portal]Windows Azure Virtual Machine (11) 在本地使用Hyper-V制作虚拟机模板,并上传至Azure (1)

    <Windows Azure Platform 系列文章目录> 本章介绍的内容是将本地Hyper-V的VHD,上传到Azure数据中心,作为自定义的虚拟机模板. 注意:因为在制作VHD的最 ...

  10. js限制文本框只可以输入数字

    封装了一下,要用的话直接调用下面getEvent函数即可   function getEvent() { if (document.all) { return window.event; //for ...