【转】【Thread】ReaderWriterLock 读写锁
ReaderWriterLock类
通常来讲,一个类型的实例对于并行的读操作是线程安全的,但是并行地更新操作则不是(并行地读和更新也不是)。 这对于资源也是一样的,比如一个文件。当保护类型的实例安全时,使用一个简单的排它锁即解决问题,但是当有很多的读操作而偶然的更新操作这就很不合理的限制了并发。一个例子就是这在一个业务程序服务器中,为了快速查找把数据缓存到静态字段中。 在这个方案中,ReaderWriterLock类被设计成提供最大容量的锁定。
ReaderWriterLock为读和写的锁提供了不同的方法——AcquireReaderLock和AcquireWriterLock。两个方法都需要一个超时参数,并且在超时发生后抛出ApplicationException异常(不同于大多数线程类的返回false等效的方法)。超时发生相当容易在资源争用严重的时候。
调用 ReleaseReaderLock或ReleaseWriterLock释放锁。 这些方法支持嵌套锁,ReleaseLock方法也支持一次清除所有嵌套级别的锁。(你可以随后调用RestoreLock类重新锁定相同的级别,它在ReleaseLock之前执行——如此来模仿Monitor.Wait的锁定切换行为)。
你可以调用AcquireReaderLock开始一个read-lock ,然后通过UpgradeToWriterLock把它升级为write-lock。这个方法返回一个可能被用于调用DowngradeFromWriterLock的信息。这个方式允许读程序临时地请求写访问同时不必必须在降级之后重新排队列。
在接下来的这个例子中,4个线程被启动:一个不停地往列表中增加项目;另一个不停地从列表中移除项目;其它两个不停地报告列表中项目的个数。前两者获得写的锁,后两者获得读的锁。每个锁的超时参数为10秒。(异常处理一般要使用来捕捉ApplicationException,这个例子中出于方便而省略了).
例子:
class Program
{
static ReaderWriterLock rw = new ReaderWriterLock ();
static List <int> items = new List <int> ();
static Random rand = new Random (); static void Main (string[] args)
{
new Thread (delegate() { while (true) AppendItem(); } ).Start();
new Thread (delegate() { while (true) RemoveItem(); } ).Start();
new Thread (delegate() { while (true) WriteTotal(); } ).Start();
new Thread (delegate() { while (true) WriteTotal(); } ).Start();
} static int GetRandNum (int max)
{ lock (rand) return rand.Next (max); } static void WriteTotal()
{
rw.AcquireReaderLock ();
int tot = ; foreach (int i in items) tot += i;
Console.WriteLine (tot);
rw.ReleaseReaderLock();
} static void AppendItem ()
{
rw.AcquireWriterLock ();
items.Add (GetRandNum ());
Thread.SpinWait ();
rw.ReleaseWriterLock();
} static void RemoveItem ()
{
rw.AcquireWriterLock ();
if (items.Count > )
items.RemoveAt (GetRandNum (items.Count));
rw.ReleaseWriterLock();
}
}
往List中加项目要比移除快一些,这个例子在AppendItem中包含了SpinWait来保持项目总数平衡。
按照请求到达的顺序,一共有四种 :
Reader-Reader,第二个不需等待,直接获得读控制权;
Reader-Writer,第二个需要等待第一个调用ReleaseReaderLock()释放读控制权后,才能获得写控制权;
Writer-Writer,第二个需要等待第一个调用ReleaseWriterLock()释放写控制权后,才能获得写控制权;
Writer-Reader,第二个需要等待第一个调用ReleaseWriterLock()释放写控制权后,才能获得读控制权。
原文链接:http://www.cnblogs.com/coderzh/articles/1586268.html
【转】【Thread】ReaderWriterLock 读写锁的更多相关文章
- C# lock 语法糖实现原理--《.NET Core 底层入门》之自旋锁,互斥锁,混合锁,读写锁
在多线程环境中,多个线程可能会同时访问同一个资源,为了避免访问发生冲突,可以根据访问的复杂程度采取不同的措施 原子操作适用于简单的单个操作,无锁算法适用于相对简单的一连串操作,而线程锁适用于复杂的一连 ...
- C# lock的语法糖原理--《.net core 底层入门》之自旋锁,互斥锁,混合锁,读写锁
在多线程环境中,多个线程可能会同时访问同一个资源,为了避免访问发生冲突,可以根据访问的复杂程度采取不同的措施 原子操作适用于简单的单个操作,无锁算法适用于相对简单的一连串操作,而线程锁适用于复杂的一连 ...
- java多线程-读写锁
Java5 在 java.util.concurrent 包中已经包含了读写锁.尽管如此,我们还是应该了解其实现背后的原理. 读/写锁的 Java 实现(Read / Write Lock Java ...
- 让C#轻松实现读写锁分离
ReaderWriterLockSlim 类 表示用于管理资源访问的锁定状态,可实现多线程读取或进行独占式写入访问. 使用 ReaderWriterLockSlim 来保护由多个线程读取但每次只采用一 ...
- C#读写锁ReaderWriterLockSlim的使用
读写锁的概念很简单,允许多个线程同时获取读锁,但同一时间只允许一个线程获得写锁,因此也称作共享-独占锁.在C#中,推荐使用ReaderWriterLockSlim类来完成读写锁的功能. 某些场合下,对 ...
- 可重入锁 公平锁 读写锁、CLH队列、CLH队列锁、自旋锁、排队自旋锁、MCS锁、CLH锁
1.可重入锁 如果锁具备可重入性,则称作为可重入锁. ========================================== (转)可重入和不可重入 2011-10-04 21:38 这 ...
- 用读写锁三句代码解决多线程并发写入文件 z
C#使用读写锁三句代码简单解决多线程并发写入文件时提示“文件正在由另一进程使用,因此该进程无法访问此文件”的问题 在开发程序的过程中,难免少不了写入错误日志这个关键功能.实现这个功能,可以选择使用第三 ...
- 锁的封装 读写锁、lock
最近由于项目上面建议使用读写锁,而去除常见的lock锁.然后就按照需求封装了下锁.以简化锁的使用.但是开发C#的童鞋都知道lock关键字用起太方便了,但是lock关键字不支持超时处理.很无奈,为了实现 ...
- Java多线程13:读写锁和两种同步方式的对比
读写锁ReentrantReadWriteLock概述 大型网站中很重要的一块内容就是数据的读写,ReentrantLock虽然具有完全互斥排他的效果(即同一时间只有一个线程正在执行lock后面的任务 ...
随机推荐
- SharePoint 2013 中的SQL Server 安全
使用SharePoint很长时间以来,都认为Sql只需要最初始的配置,即不再需要管理和维护:而事实上,Sql的管理和安全,都是和SharePoint环境的稳定性息息相关的,所以,要绝对重视ShareP ...
- Android 手机号码格式验证
package com.app.android01 ; import android.app.Activity; import android.os.Bundle; import android.te ...
- Android NDK
1.Android之NDK开发 http://www.cnblogs.com/devinzhang/archive/2012/02/29/2373729.html
- Python数据结构与算法--算法分析
在计算机科学中,算法分析(Analysis of algorithm)是分析执行一个给定算法需要消耗的计算资源数量(例如计算时间,存储器使用等)的过程.算法的效率或复杂度在理论上表示为一个函数.其定义 ...
- UnityShader之固定管线命令Combine纹理混合【Shader资料4】
Combine,纹理混合. 我们先看圣典上给的解释. 纹理在基本的顶点光照被计算后被应用.在着色器中通过SetTexture 命令来完成. SetTexture 命令在片面程序被使用时不会生效:这种模 ...
- 不小心改了Xcode系统的头文件,运行报错,解决办法
- 插入排序(java版)
public class InsertSortTest{ public static void InsertSort(int[] source) { //默认第一个元素已排序 for (int i = ...
- Spring web.xml配置文件解析
概要解析
- 【整理贴】DBA-常用到的动态视图分析语句
测试应用环境:SQL2008 R2.SQL2012.SQL2014 --语句1:获取前20逻辑读取次数或逻辑写入次数或CPU 时间 SELECT TOP 20 SUBSTRING(qt.TEXT, ( ...
- LVS四种实现模式详解
一.集群cluster 当后端服务器承受不住访问的压力,提高服务器性能的解决方案会极大增加成本时,人们提出了横向扩展的解决方案.增加一台或几台服务器,提供相同的服务,通过前段分发器将访问量均匀的分配到 ...