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参数创建一个方法并锁定以实现类似linq链接的方法(但是并行运行锁定,这是一个挑战):
Lock(lockA).Lock(lockB).Lock(lockC).Run( () => ...);
或许还有另一种方式?
答案 0 :(得分:8)
我会使用同步锁:
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中是好的模式/设计,但它会起作用;)
对于异步。分区化并不是一个好主意。为什么?
如果某个线程将进入监视器,则同一个线程必须离开它(带锁定退出)。因此,如果你在objA
(f.e.)内锁定Parallel.ForEach
,你就不会知道哪个线程已经完成了它。所以你不能发布它。