在系统中,我们有通过特定参数锁定对象的方法。 作为实现,我们使用LockManager和Enter方法接收锁的密钥,检查内部字典中是否存在锁对象,如果没有,则创建它然后锁定。
我想要做的是为特定锁定设置“X预期时间”,如果对象被锁定超过X时间,我想在我们的日志中写一条消息。
以下是我的锁管理器的源代码:
public class MyLockManager<T>
{
protected Dictionary<T, object> LockDictionary { get; private set; }
public MyLockManager()
{
LockDictionary = new Dictionary<T, object>();
}
/// <summary>
/// Enters a lock on the key.
/// </summary>
/// <param name="key">The key to lock.</param>
public virtual void Enter(T key)
{
if (!LockDictionary.ContainsKey(key))
{
lock (LockDictionary)
{
if (!LockDictionary.ContainsKey(key))
{
LockDictionary.Add(key, new object());
}
}
}
object lockObj = LockDictionary[key];
Monitor.Enter(lockObj);
}
/// <summary>
/// Releases the lock on the key.
/// </summary>
/// <param name="key">The key to release.</param>
public virtual void Exit(T key)
{
if (LockDictionary.ContainsKey(key))
{
Monitor.Exit(LockDictionary[key]);
}
}
}
现在我想添加一个额外的方法,假设将调用LockTimoutHandler(T键),如果特定键的对象被锁定超过X时间。
为了做到这一点,我想为“Enter”和“Exit”方法添加一些逻辑。当Enter调用时, 会以某种方式注册 以在X时间内运行LockTimoutHandler,并且当调用“Exit”时, 某些内容将以某种方式取消注册
我的问题是我可以使用什么而不是 某些 ?我如何安排方法在X时间运行,如果之前发生退出,那么删除计划。它必须非常快,因为在我们的情况下性能非常重要。我知道Timer对象......它可以延迟执行方法,但它的性能是否足够好?我还有哪些其他选择?
注意:为了清楚起见,我不是在谈论 TryEnter 。当对象无法锁定特定时间时,我不想抓住这种情况,我想抓住已经锁定了太长时间的对象。
谢谢!
答案 0 :(得分:2)
我们有类似的要求并以这种方式解决:
这将根据需要保留尽可能多的计时器,但不会更多,并且只会产生分配/解除分配的成本一次。由于无法更改计时器的状态对象,因此需要更改其内容。
答案 1 :(得分:1)
我认为你可以做得更简单。计时器是一个非常轻量级的对象,我不会试图限制他们的计数。所有计时器都在线程池的特殊线程中运行,它们非常便宜。
只需创建一个计时器字典(如果它将从不同的线程中使用,您可能希望将其更改为ConcurrentDictionary
:
var timers = new Dictionary<T, Timer>();
将项目添加到列表时,请使用此代码设置超时:
var timer = new Timer(o => LogMessage("key {0} is being held too long", key));
timer.Change(timeout, Timeout.Infinite);
timers.Add(key, timer);
请注意,在指定的超时后,计时器只会执行一次。 当项目被释放时,只需从字典中删除计时器:
Timer timer;
if (timers.TryGetValue(key, out timer))
{
timer.Dispose();
timers.Remove(key);
}