【问题标题】:Briefly releasing a lock in .NET简单地释放 .NET 中的锁
【发布时间】:2013-09-28 03:03:01
【问题描述】:

我在多个线程之间共享一个资源,使用模式如下:

  • 线程 1 不断使用受保护的资源。

  • 线程 2..N 需要在很短的时间内不频繁地与受保护资源进行交互。

我希望线程 1 在其工作周期的特定时间持续持有保护资源的锁,让其他线程等待轮到它们。如果没有其他线程碰巧在等待,它应该立即重新获得锁并继续它的工作。

我想一种方法是这样的:

lock (resource)
{
    while (!stop)
    {
        resource.DoWorkIteration();

        // give other threads a chance
        Monitor.Exit(resource);
        Thread.Sleep(0); 
        Monitor.Enter(resource);
    }
}

但是,Sleep(0) 将让步给任何准备运行的线程,而不仅仅是等待这个特定资源的线程。

有没有更好的方法来避免不必要的让步?

【问题讨论】:

  • 如果在Exit()Enter() 之间抛出异常并且lock 块尝试释放未拥有的资源会发生什么?

标签: .net multithreading synchronization locking


【解决方案1】:

这是一个一般性建议,但您应该协调对资源的访问,而不是竞争资源。原因是锁定、解锁和上下文切换的开销不可忽略,而且它总是存在死锁的危险。释放和重新获取锁也不是免费的,所以最好避免。

在您的情况下,我建议线程 2..N 需要完成的资源实际上由线程 1 完成。为此,请使用存储在队列中的回调(最好是非阻塞操作的回调)。当队列为空时,线程 1 做自己的事情,否则它会从队列中弹出一个回调并执行它。如果您需要结果,请使用请求线程等待的事件。也许您还可以利用 .Net 用于将非 UI 线程的调用委托给 UI 元素的现有系统。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-06-18
    • 1970-01-01
    • 1970-01-01
    • 2011-11-15
    • 2014-12-25
    • 1970-01-01
    • 2018-12-19
    • 2016-07-22
    相关资源
    最近更新 更多