C#3.0核心技术-第19章线程-全新翻译注释-19.13(2)

来源:互联网 发布:展板排版用什么软件 编辑:程序博客网 时间:2024/05/08 18:02

19.13.1 可升级的锁与递归

有些时候,在一个单一的原子操作中以一个读锁交换一个写锁很有用。例如,假定你想要加入一个条目到list中,仅当这个条目没有已经在list中。理想地,你希望最小化花费在持有(互斥的)写锁上的时间,所以你可以像下面一样处理:

1. 获得一个读锁。

2. 测试是否条目已经在list中,如果是这样,释放锁并返回。

3. 释放读锁。

4. 获得一个写锁。

5. 加入条目。

问题是另一个线程可能在第3步和第4步之间潜入并修改list(例如,加入相同的条目)。ReaderWriterLockSlim通过一个被称为可升级锁的第三种锁来解决这个问题。一个可升级的锁就像一个读锁一样,除了它后来能够在一个原子操作中被提升为一个写锁。这里是我们如何使用它:

1. 调用EnterUpgradeableReadLock。

2. 执行基于读的活动(例如,测试条目是否已经在list中)。

3. 调用EnterWriteLock(这个将可升级锁转化为一个写锁)。

4. 执行基于写的活动(例如,加入条目到list中)。

5. 调用ExitWriteLock(这个将写锁转换回一个可升级锁)。

6. 执行任何其它基于读的活动。

7. 调用ExitUpgradeableReadLock。

从调用者的角度看,这有点像嵌套或者递归锁定。功能上,尽管,在第3步,ReaderWriterLockSlim原子性地释放你的读锁并获得一个全新的写锁。

这里有另外一个可升级锁和读锁之间的重要区别。尽管一个可升级锁能够与任意数量的读锁共存,同一时间仅有一个可升级锁被取得。这通过序列化竞争的转换来防止转换死锁—就像SQL服务器中的更新锁一样:

SQL Server

ReaderWriterLockSlim

Share lock

Read lock

Exclusive lock

Write lock

Update lock

Upgradeable lock

我们可以通过改变前一个例子中的Write方法来演示一个可升级锁,使得它仅当一个数没有已经在list中时才加入这个数到list中:

clip_image001

原文注:

ReaderWriterLock也可以做锁转换—但是不可靠,因为它不支持升级锁的概念。这就是为什么ReaderWriterLockSlim的设计者以一个新类作为全新的开始。

原创粉丝点击