锁定超时模式

lock使用这种模式

 if(Monitor.Enter(lock)) try { ... } finally { Monitor.Exit(lock); } // using this style to reduce post "height" 

如果我们不想等待无限,我们可以提供超时

 if(!Monitor.TryEnter(lock, timeout)) throw new TimeoutException(); try { ... } finally { Monitor.Exit(lock); } 

我有方法,方法必须在开始做任何事情之前获得多个锁。 这看起来很糟糕:

 if(!Monitor.TryEnter(lockA, timeout)) throw new TimeoutException(); try { if(!Monitor.TryEnter(lockB, timeout)) throw new TimeoutException(); try { if(!Monitor.TryEnter(lockC, timeout)) throw new TimeoutException(); try { ... // more of such constructions } finally { Monitor.Exit(lockC); } } finally { Monitor.Exit(lockB); } } finally { Monitor.Exit(lockA); } 

它有问题:

  • 看起来很难看(方法代码是缩进的,想象它将如何查找lockZ ),可以通过将方法代码放入另一个方法来解决。

  • 锁定是同步发生的,因此最糟糕的成功案例可能需要的时间略小于所有超时的总和。

有没有办法改善这种超时模式?

我正在考虑使用delegate参数和lock来创建一个类似linq chaining的方法(但是也要并行运行锁,这是一个挑战):

 Lock(lockA).Lock(lockB).Lock(lockC).Run( () => ...); 

或许还有另一种方式?

我会使用同步锁:

 using System; using System.Threading; public class MyLock : IDisposable { private object lockObj; public Lock(object lockObj, TimeSpan timeout) { this.lockObj = lockObj; if (!Monitor.TryEnter(this.lockObj, timeout)) throw new TimeoutException(); } public void Dispose() { Monitor.Exit(lockObj); } } 

用法:

 using(new MyLock(lockA, new TimeSpan.FromSeconds(1))) using(new MyLock(lockB, new TimeSpan.FromSeconds(2))) using(new MyLock(lockC, new TimeSpan.FromSeconds(3))) { // your code } 

不知道ctor中的“锁定”是否是好的模式/设计,但它会起作用;)

对于异步。 分区化并不是一个好主意。 为什么? 如果某个线程将进入监视器,则同一个线程必须离开它(带锁定退出)。 因此,如果您在Parallel.ForEach (fe)中锁定objA ,您将无法知道哪个线程已完成它。 所以你将无法发布它。