C# Minimal API多用户并发请求处理:是否需实现锁机制?
问题分析与解决方案
你的代码存在严重的线程安全问题,必须调整才能保证多用户请求互不干扰,以下是具体分析和解决思路:
问题根源
你声明的calcObj是全局单实例,而Calculator类的Addition和Multiplication方法依赖实例私有字段A、B——这两个字段会被不同请求的线程并发修改。比如:
- 用户1调用
Addition(1,2),刚把A=1、B=2设置好,还没返回结果; - 用户2的线程就调用
Multiplication(3,4),把A改成3、B改成4; - 最终用户1得到的加法结果会变成
3+4=7,完全不符合预期。
线程池分配线程处理请求只是调度方式,无法解决共享实例状态被并发修改的问题。
最优解决方案:无状态设计(推荐)
直接重构Calculator类,去掉实例私有字段,让方法仅依赖输入参数完成计算,彻底消除共享状态:
class Calculator { public double Addition(double a, double b) { return a + b; } public double Multiplication(double a, double b) { return a * b; } }
更进一步,可将方法改为静态,连实例都无需创建:
class Calculator { public static double Addition(double a, double b) { return a + b; } public static double Multiplication(double a, double b) { return a * b; } }
对应的API端点修改为:
app.MapGet("/calc", (int a, int b) => { var additionResult = Calculator.Addition(a, b); var multiplicationResult = Calculator.Multiplication(a, b); return Results.Ok(new Message() { Text = $"Result for addition: {additionResult}, Result for multiplication: {multiplicationResult}" }); });
这种无状态设计天然线程安全,没有任何并发干扰风险,且性能最优,完全适配高并发场景。
备选方案:每个请求创建独立实例
如果一定要保留Calculator的实例字段设计(不推荐,因为没必要),可以去掉全局的calcObj,改为每个请求创建自己的Calculator实例:
app.MapGet("/calc", (int a, int b) => { var calcObj = new Calculator(); var additionResult = calcObj.Addition(a, b); var multiplicationResult = calcObj.Multiplication(a, b); return Results.Ok(new Message() { Text = $"Result for addition: {additionResult}, Result for multiplication: {multiplicationResult}" }); });
每个请求的Calculator实例独立,字段A、B不会被其他请求干扰,同样无需锁。
不推荐:使用锁机制
锁(比如lock语句)确实能保护共享状态,但会带来明显的性能开销——高并发场景下,大量请求会因锁竞争排队,严重降低接口吞吐量。而且你的场景完全可以通过无状态或独立实例解决,锁属于冗余且低效的方案。
内容的提问来源于stack exchange,提问作者user1911091
相关产品推荐
相关产品推荐

