《C#多线程编程实战(原书第2版)》——2.9 使用ReaderWriterLockSlim类

简介:

本节书摘来自华章出版社《C#多线程编程实战(原书第2版)》一书中的第2章,第2.9节,作者(美)易格恩·阿格佛温(Eugene Agafonov),黄博文 黄辉兰 译,更多章节内容可以访问云栖社区“华章计算机”公众号查看。

2.9 使用ReaderWriterLockSlim类

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

2.9.1 准备工作

为了学习本节,你需要安装Visual Studio 2015。除此之外无需其他准备。
本节的源代码放置在BookSamplesChapter2Recipe8目录中。

2.9.2 实现方式

请执行以下步骤来了解如何使用ReaderWriterLockSlim类来创建一个线程安全的机制,在多线程中对集合进行读写操作:

1.启动Visual Studio 2015。新建一个C#控制台应用程序项目。

2.在Program.cs文件中加入以下using指令:


481bc8a757eccea5ec113c144cf83630888654e7

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


3713d9ad1544a32f2eafabdd5ed9d01f442ad672


6530b3481a70d932fb3d1fec44a6e0506af1cd75


9d21433d5c814dc1bbd47f2e9944021792a932b1

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


509c2db59c0015805f15b09474f39acbfa014cf8


91bd29179acf8b33f337ddf2168effb139fe1566

5.运行程序。

2.9.3 工作原理

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

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

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

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

相关文章
|
9天前
|
JSON 网络协议 安全
【Java】(10)进程与线程的关系、Tread类;讲解基本线程安全、网络编程内容;JSON序列化与反序列化
几乎所有的操作系统都支持进程的概念,进程是处于运行过程中的程序,并且具有一定的独立功能,进程是系统进行资源分配和调度的一个独立单位一般而言,进程包含如下三个特征。独立性动态性并发性。
54 1
|
9天前
|
JSON 网络协议 安全
【Java基础】(1)进程与线程的关系、Tread类;讲解基本线程安全、网络编程内容;JSON序列化与反序列化
几乎所有的操作系统都支持进程的概念,进程是处于运行过程中的程序,并且具有一定的独立功能,进程是系统进行资源分配和调度的一个独立单位一般而言,进程包含如下三个特征。独立性动态性并发性。
45 1
|
开发框架 .NET C#
C#|.net core 基础 - 删除字符串最后一个字符的七大类N种实现方式
【10月更文挑战第9天】在 C#/.NET Core 中,有多种方法可以删除字符串的最后一个字符,包括使用 `Substring` 方法、`Remove` 方法、`ToCharArray` 与 `Array.Copy`、`StringBuilder`、正则表达式、循环遍历字符数组以及使用 LINQ 的 `SkipLast` 方法。
370 8
|
存储 C# 索引
C# 一分钟浅谈:数组与集合类的基本操作
【9月更文挑战第1天】本文详细介绍了C#中数组和集合类的基本操作,包括创建、访问、遍历及常见问题的解决方法。数组适用于固定长度的数据存储,而集合类如`List<T>`则提供了动态扩展的能力。文章通过示例代码展示了如何处理索引越界、数组长度不可变及集合容量不足等问题,并提供了解决方案。掌握这些基础知识可使程序更加高效和清晰。
200 6
lua面向对象(类)和lua协同线程与协同函数、Lua文件I/O
Lua的面向对象编程、协同线程与协同函数的概念和使用,以及Lua文件I/O操作的基本方法。
149 4
lua面向对象(类)和lua协同线程与协同函数、Lua文件I/O
|
10月前
|
Java
【JavaEE】——多线程常用类
Callable的call方法,FutureTask类,ReentrantLock可重入锁和对比,Semaphore信号量(PV操作)CountDownLatch锁存器,
|
10月前
|
Java 程序员 调度
【JavaEE】线程创建和终止,Thread类方法,变量捕获(7000字长文)
创建线程的五种方式,Thread常见方法(守护进程.setDaemon() ,isAlive),start和run方法的区别,如何提前终止一个线程,标志位,isinterrupted,变量捕获
|
10月前
|
安全 Java API
【JavaEE】多线程编程引入——认识Thread类
Thread类,Thread中的run方法,在编程中怎么调度多线程
|
11月前
|
安全 Java
Java多线程集合类
本文介绍了Java中线程安全的问题及解决方案。通过示例代码展示了使用`CopyOnWriteArrayList`、`CopyOnWriteArraySet`和`ConcurrentHashMap`来解决多线程环境下集合操作的线程安全问题。这些类通过不同的机制确保了线程安全,提高了并发性能。
190 1
|
12月前
|
Java 开发者
在Java多线程编程中,创建线程的方法有两种:继承Thread类和实现Runnable接口
【10月更文挑战第20天】在Java多线程编程中,创建线程的方法有两种:继承Thread类和实现Runnable接口。本文揭示了这两种方式的微妙差异和潜在陷阱,帮助你更好地理解和选择适合项目需求的线程创建方式。
208 3

热门文章

最新文章