【问题标题】:C# release lock automatically after timeoutC#超时后自动释放锁
【发布时间】:2020-01-31 04:42:16
【问题描述】:

有没有人知道实现锁的最佳方法是什么,以便在 X 秒后自动释放?

【问题讨论】:

  • 这听起来是个坏主意。你想做什么?
  • 我同意 SLaks - 等待 X 秒锁定是“不寻常的”。
  • 理想情况下,我需要组合一个泛型类,该类将引发异常或在超时后自动清除锁定,即使用锁定类的方法出现问题
  • 考虑到这一点,我认为您应该考虑单锁的替代设计。最好考虑一下可能“出错”的“事物的类型”是什么,并尝试编写一个解决方案,将问题分解为几个阶段,每个阶段之间都有可能恢复。 “锁”是为了保护数据不被多个线程同时访问——不要用这个提议的时间锁机制消除线程安全——找到其他方法。您不应该在“锁定”代码中让那个“出错”线程处于活动状态 - 找到某种方法来中止它?
  • 作为一个用例,我需要能够锁定一个 Id 但不超过 5 秒,之后其他人才能获得锁定。由于我们持久性的性质(具有预期版本),如果两个不同的线程都进入锁定区域,则不会出现竞争条件问题,我只是想确保挂起的线程不会阻塞其他线程。

标签: c# locking


【解决方案1】:

假设您正在寻找在 X 秒内触发的事件,那么我认为目前没有任何核心 Mutex 对象可以提供您正在寻找的功能类型。

您可以通过使用 System.Timer(在 X 秒内触发并释放锁定的互斥锁)或使用 Sleep 持续 X 秒的线程来创建此类功能 - 我更喜欢第一种方法。

但是,这两个都将在用户/应用程序层内安排 - 因此您必须等待它们安排好。

【讨论】:

    【解决方案2】:

    您可以使用Monitor.TryEnter 实现此目的。请参考以下 -

    Synchronization problems with Monitor class in WCF service

    if(Monitor.TryEnter(lockObj, timeout)) {
        try {
            ...
        } finally {
            Monitor.Exit(lockObj);
        }
    }
    

    【讨论】:

    • 不确定您是否完全理解我 - Monitor.TryEnter(据我所知)将接受一个时间跨度,之后它将停止尝试获取锁。就我而言,我有锁并希望它在超时后自动释放
    • @Johnv2020 如果你有锁,等待一段时间然后释放它;)
    【解决方案3】:

    在 Web 开发中,我一直在使用滑动超时进行缓存。也许您可以使用缓存的对象作为锁?

    这里讨论了非 Web 应用程序中的缓存技术:

    Caching in C# without System.Web

    【讨论】:

      【解决方案4】:

      您可以将 TransactionScope 与 TransactionOptions 超时参数一起使用。

      using (TransactionScope tx = new TransactionScope(TransactionScopeOption.RequiresNew,
                          new TransactionOptions() { Timeout = new TimeSpan(0, 0, 10) }))
      

      时间结束后,你会收到一个 TransactionAbortedException 并且锁应该被释放。

      会是这样的:

      lock(_lock)
      {
          try
          {
              using (TransactionScope tx = new TransactionScope(TransactionScopeOption.RequiresNew,
                              new TransactionOptions() { Timeout = new TimeSpan(0, 0, 10) }))
              {
                  //do somenting important stuff
                  tx.Complete();
                  tx.Dispose();  // just remembering that will be disposed.
              }
          }
          catch (TransactionAbortedException tex)
          {
              throw new Exception("Operation Timeout");
          }
          catch (Exception)
          {
              throw; // do whatever you want
          }
      }
      

      【讨论】:

        猜你喜欢
        • 2011-05-08
        • 1970-01-01
        • 1970-01-01
        • 2018-05-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-06-04
        相关资源
        最近更新 更多