部分线程锁:线程安全和不安全代码的混合

Partial thread lock: mix of thread-safe and unsafe code

我有两种方法,比如说,read()init()

read 是可重入和线程安全的;它可以(并且应该)由多个线程并行执行。

但是,它们的任何其他混合都不是线程安全的;例如如果 init 正在执行,read 必须阻塞,反之亦然,更不用说 init 本身了。 (事情很复杂,因为它都是非托管代码的包装器)。

在这种情况下如何组织锁(在 .net、C# 或 VB 中)?

init 本身似乎微不足道:我可以将其包装在标准 lock () / SyncLock 机制中。但是是否有一个类似的简单机制允许 read 到:

  1. 阻止用于 init 的同一个锁对象,但不获取其独占性(否则 read 将在其上阻止自己)。
  2. 当块被释放时,标记另一个对象(互斥锁?),除了它自己的锁之外 init 应该阻塞(但在 read 中我们不检查它)。
  3. 运行代码。
  4. 释放第二个对象。

在多线程中经常发生,肯定有很多我不是很熟悉的陷阱。例如,我看到读锁对象可能会被多个并行读取 运行 标记多次,并且必须在 init 可以执行之前完全展开。这一切感觉都是相当普遍的情况,必须有处理它的标准方法...

ReaderWriterLock 或 ReaderWriterLockSlim(在新代码中首选)类 似乎是您在这里想要的,您的 init() 方法是编写器。

ReaderWriterLock is used to synchronize access to a resource. At any given time, it allows either concurrent read access for multiple threads, or write access for a single thread. In a situation where a resource is changed infrequently, a ReaderWriterLock provides better throughput than a simple one-at-a-time lock, such as Monitor.

ReaderWriterLock works best where most accesses are reads, while writes are infrequent and of short duration. Multiple readers alternate with single writers, so that neither readers nor writers are blocked for long periods.

自 1.1 版以来,它一直是 .NET 框架的一部分,并记录在案 here