c# - 在异步或同步操作中使用监视器锁
问题描述
我正在尝试提供一种锁定全局资源的解决方案,以强制锁定访问并且可用于同步或异步操作。
我创建了一个通用类状态:
public class State<T>
{
public class LockedState : IDisposable {
public LockedState(State<T> state) { this.state = state; Monitor.Enter(this.state.theLock); } // would be great if this could be private
public void Dispose() => Monitor.Exit(this.state.theLock);
public ref T Val { get { return ref state.t; } }
readonly State<T> state;
};
public State() { }
public State(T t) { this.t = t; }
public LockedState Locked { get { return new LockedState(this); } }
readonly object theLock = new object();
T t;
}
这里的想法是我可以在 Program 类中拥有一个全局“商店”:
public class Program {
static public readonly State<ImmutableList<int>> TheList = new State<ImmutableList<int>>(ImmutableList<int>.Empty);
static public readonly State<SomeType> SomeType = new State<SomeType>(SomeType());
}
然后访问状态的唯一方法是像这样获取锁:
using (var lTheList = Program.TheList.Locked) {
lTheList.Val = lTheList.Val.Add(5));
}
在我的情况下,它比普通锁效果更好,因为它在获取/设置之前强制锁定(你不能忘记锁定)
(旁注这是一个好策略吗?)
问题是我不能在异步代码中使用上述内容:
using (var someType = Program.SomeType.Lock()) {
var x = await someType.Val.SomeAsyncOp();
}
我得到一个例外:Object synchronization method was called from an unsynchronized block of code
我发现这篇文章如何保护可能在多线程或异步环境中使用的资源?它有一个 AsyncLock 类但是我不明白如何将像 AsyncLock 这样的类放入我的 StateLock 类中。
可以State.Lock()
返回可用于同步和异步调用者的锁定状态吗?这真的是我要找的!
如果不是,我最好的前进方式是什么?使用SemaphoreSlim
和拥有一个State.Lock()
和一个State.AsyncLock()
?
谢谢!
解决方案
您不能Monitor
在这里使用,因为Monitor
(aka lock
) 本质上是基于线程的,并且需要您从获取锁的同一线程中“退出”锁 - 这正是您在代码中很少期望的情况。async
相反,请考虑 a SemaphoreSlim
,您可以从中获取和释放令牌,但它不是线程绑定的。
伪代码:
// usually a field somewhere
SemaphoreSlim obj = new SemaphoreSlim(1);
// acquire lock:
obj.Wait(); // or await obj.WaitAsync() if want async acquire
// release lock:
obj.Release(); // often in a "finally"
推荐阅读
- java - 如何通过 Android 应用与外部 SQL 数据库通信?
- c# - 对于 .net 核心 Web 应用程序,是否只能跨多个控制器(即同时用于 REST 和 Grpc APi 控制器)使用一个 IServiceProvider。
- python - 如何修复 Docker 依赖项安装?
- java - 使用 Date 类将给定日期的字符串与当前日期进行比较时获取 Null 对象引用异常
- rxjs - 如何以更惯用的 rxjs 方式处理这些功能
- node.js - express.Router() 与 express 中的 express()
- jmeter - 如何通过 Jmeter JMS 点对点向 JMS 队列发送字节消息
- reactjs - React-Testing-Library(RTL):动画导致带有 React Pose 的 TypeError
- firebase - Firebase 部署正在部署我的源文件夹未加密
- jquery - AJAX 调用 .NET Core API 失败