使用ReaderWriterLockSlim创建一个线程安全的机制,在多线程中对一个集合进行读写操作。ReaderWriterLockSlim代表了一个管理资源访问的锁,允许多个线程同时读取,以及独占写。

代码Demo:

using System;
using System.Threading;
using System.Collections.Generic;

在Main方法下面加入以下代码片段:

static ReaderWriterLockSlim _rw = new ReaderWriterLockSlim();
static Dictionary<int, int> _items = new Dictionary<int, int>();

static void Read()
{
Console.WriteLine("Reading contents of a dictionary");
while (true)
{
try
{
_rw.EnterReadLock();
foreach (var key in _items.Keys)
{
Thread.Sleep(TimeSpan.FromSeconds(0.1));
}
}
finally
{
_rw.ExitReadLock();
}
}
}
static void Write(string threadName)
{
while (true)
{
try
{
int newKey = new Random().Next(250);
_rw.EnterUpgradeableReadLock();
if (!_items.ContainsKey(newKey))
{
try
{
_rw.EnterWriteLock();
_items[newKey] = 1;
Console.WriteLine("New key {0} is added to a dictionary by a {1}", newKey, threadName);
}
finally
{
_rw.ExitWriteLock();
}
}
Thread.Sleep(TimeSpan.FromSeconds(0.1));
}
finally
{
_rw.ExitUpgradeableReadLock();
}
}
}

在Main方法中加入以下代码片段:

new Thread(Read) { IsBackground = true }.Start();
new Thread(Read) { IsBackground = true }.Start();
new Thread(Read) { IsBackground = true }.Start();

new Thread(() => Write("Thread 1")) { IsBackground = true }.Start();
new Thread(() => Write("Thread 2")) { IsBackground = true }.Start();

Thread.Sleep(TimeSpan.FromSeconds(30));

工作原理

当主程序启动时,同时运行了三个线程来从字典中读取数据,还有另外两个线程向该字典中写入数据。我们使用readerWriterLockSlim类来实现线程安全,该类转为这样的场景而设计。

这里使用两种锁:读锁允许多线程读取数据,写锁在被释放前会阻塞了其它线程的所有操作。获取读锁时还有一个场景,即从集合中读取数据时,根据当前数据而决定是否获取一个写锁并修改该集合。一旦得到写锁,会阻止阅读者读取数据,从而浪费大量的时间,因此获取写锁后集合会处于阻塞状态。为了最小化阻塞浪费的时间,可以使用EnterUpgradeableReadLock和ExitUpgradeableReadLock方法。先获取读锁后读取数据。如果发现必须修改底层集合,只需使用EnterLock方法升级锁,然后快速执行一次写操作,最后使用ExitWriteLock释放写锁。

本例,我们先生成一个随机数。然后获取读锁并检查该数是否存在于字典的键集合中。如果不存在,将读锁更新为写锁然后将该锁新键键入到字典中。始终使用try/finaly代码块来确保在捕获后一定会释放锁,这是一项好的实践。

所有的线程都被创建为后台线程。主线程在所有后台线程完成后等待30秒。

线程同步-使用ReaderWriterLockSlim类的更多相关文章

  1. 多线程状态与优先级、线程同步与Monitor类、死锁

    一.线程状态 二.线程优先级 三.初步尝试多线程 class Program { static void Main(string[] args) { while (true) { MessagePri ...

  2. 线程同步之ManualResetEvent类的用法

    笔者的一台激光测厚设备的软件, 它有一个运动线程, 一个激光数据处理线程. 运动线程做的事就是由A点移动到B点, 然后再由B点移动回A点. 激光处理线程要做的事就是采集指定数量点的激光数据, 随着采集 ...

  3. 线程同步工具 Semaphore类使用案例

    参考博文 : 线程同步工具(一) 线程同步工具(二)控制并发访问多个资源 并发工具类(三)控制并发线程数的Semaphore 使用Semaphore模拟互斥锁 当一个线程想要访问某个共享资源,首先,它 ...

  4. 线程同步工具 Semaphore类的基础使用

    推荐好文: 线程同步工具(一) 线程同步工具(二)控制并发访问多个资源 并发工具类(三)控制并发线程数的Semaphore 简介 Semaphore是基于计数的信号量,可以用来控制同时访问特定资源的线 ...

  5. JUC——线程同步辅助工具类(Semaphore,CountDownLatch,CyclicBarrier)

    锁的机制从整体的运行转态来讲核心就是:阻塞,解除阻塞,但是如果仅仅是这点功能,那么JUC并不能称为一个优秀的线程开发框架,然而是因为在juc里面提供了大量方便的同步工具辅助类. Semaphore信号 ...

  6. 线程同步-使用SimaphoreSlim类

    SimaphoreSlim类是作为Semaphore类的轻量级版本的.该类限制了同时访问同一个资源的线程数量. 代码Demo: using System;using System.Threading; ...

  7. 线程同步-使用CountDownEvent类

    CountDownEvent类:信号类,等待直到一定数量的操作完成. 代码Demo: using System; using System.Threading; Main方法下面加入以下代码片段: p ...

  8. JUC——线程同步辅助工具类(Exchanger,CompletableFuture)

    Exchanger交换空间 如果现在有两个线程,一个线程负责生产数据,另外一个线程负责消费数据,那么这个两个线程之间一定会存在一个公共的区域,那么这个区域的实现在JUC包之中称为Exchanger. ...

  9. 【WIN32进阶之路】:线程同步技术纲要

    前面博客讲了互斥量(MUTEX)和关键段(CRITICAL SECTION)的使用,想来总觉不妥,就如盲人摸象一般,窥其一脚而言象,难免以偏概全,追加一篇博客查遗补漏. win32下的线程同步技术分为 ...

随机推荐

  1. Netty实现的一个异步Socket代码

    本人写的一个使用Netty实现的一个异步Socket代码 package test.core.nio; import com.google.common.util.concurrent.ThreadF ...

  2. 升级SilverLight为5.1.50907.0后,VS调试时报“无法启动调试--未安装 Silverlight Developer 运行时。请安装一个匹配版本”的处理办法

    作者: zyl910 一.问题 今天需要调试一个SilverLight程序.运行时ie弹出了一个升级提示,于是手贱点了升级. 随后便悲剧了,VS调试时报"无法启动调试--未安装 Silver ...

  3. Visual Studio 2015 update 3各版本下载地址

    微软在06月27日发布了Visual Studio 2015 Update 3 .在MSDN中微软也提供下载,而且MSDN的Visual Studio 2015 Update 3与官方免费下载的文件是 ...

  4. 模拟真实点击click,专门对付clickoutside

    var evmousedown = document.createEvent('HTMLEvents'); // evmousedown.clientX = 88 // evmousedown.cli ...

  5. Cmake find_package 需要指定具体的so

    需要使用cmake的find_package将boost库添加到项目中,通过cmake --help-module FindBoost 可以查看cmake引入Boost的帮助信息: 可以看到,Boot ...

  6. 两台linux服务器各有两个不同的用户 其中一个服务器可以无密码登录服务器

    服务器A:普通用户USERA 服务器B:普通用户USERB 把USERA的公钥写入服务器B用户USERB的authorized_keys中 USERA能普能用户登录然后服务器A,然后再登录服务器B: ...

  7. Asp.Net WebApi 跨域设置

    跨越问题主要发生在客户端ajax请求时,为了安全设置,默认webapi是不允许ajax跨越请求的,不过有方法设置让支持跨越,我说说最常见的两种方法 一.jquery jsonp 缺点:JSONP也有局 ...

  8. Win2012R2 AD主域控登录密码忘记

    按照普遍的修改cmd.exe 的方法,还需要注意,DC主控制器修改密码需要在后面加上 /domain net user administrator 123 /domain

  9. phpunit assert断言分类整理

    布尔类型 方法名 含义 参数 返回值 assertTrue 断言为真     assertFalse 断言为假     NULL类型 方法名 含义 参数 返回值 assertNull 断言为NULL ...

  10. mongodb应用

    一.概述 NoSQL,指的是非关系型的数据库.NoSQL有时也称作Not Only SQL的缩写,是对不同于传统的关系型数据库的数据库管理系统的统称.NoSQL用于超大规模数据的存储.(例如谷歌或Fa ...