ASP.NET Core Web API 应用程序是不是可能出现死锁或应用程序挂起状态
Posted
技术标签:
【中文标题】ASP.NET Core Web API 应用程序是不是可能出现死锁或应用程序挂起状态【英文标题】:Is deadlock or application hung state possible for ASP.NET Core Web API applicationASP.NET Core Web API 应用程序是否可能出现死锁或应用程序挂起状态 【发布时间】:2022-01-13 04:10:59 【问题描述】:我有一个 ASP.NET Core 3.1 Web API 应用程序,它有一个后台主机服务,我在其中编写了以下代码来模拟应用程序的死锁:
public class Worker : IHostedService
public Task StartAsync(CancellationToken cancellationToken)
var a = new object();
var b = new object();
lock (a)
lock (b)
// other thread
lock (b)
lock (a)
return Task.CompletedTask;
应用程序正在运行,但应用程序不会死锁或挂起状态,我仍然可以访问 web api 端点并且结果返回给我。
是否有可能使正在运行的 Web 应用程序进入死锁或挂起状态,以便 API 的 NONE 给出任何 200 结果?
谢谢。
【问题讨论】:
只需添加一个测试,它会产生多个线程,比如 100 并运行 10 分钟,你就会知道答案 以其当前形式我会说不,除非你有从不同线程多次调用 StartAsync 的东西......,看到我看到 IHostedService,我猜这是从 1 个线程调用的只有..所以你永远不会有竞争线程.. 答案很简单Is deadlock or application hung state possible for ASP.NET Core Web API application
YES 因为你的意思的范围不够具体,以至于它永远不会,因为它只是语言的一个特征/用法。我认为您应该更改标题,“对于此代码”,如果由多个线程调用,答案是肯定的。
@Seabizkit,感谢您的回复。能否请您提供一些示例代码?
@user584018 我已经说明了一些事情,1 这不是从网络请求中调用的吗?那么为什么这是问题的一部分,2你正常启动 IHostedService 的方式是在 1 个线程上,所以没有迹象表明它是如何从多个线程调用的。 3 它的表述方式确实构成了一个 gd 问题……也就是说,我是否有可能跳 3 次。 4 可以编写一个测试,但我们离开了 IHostedServic。就像操作的真正问题一样,是什么让您认为这是由多个线程调用的?别管实际的问题。
【参考方案1】:
正如所写,当前方法将从不死锁。
锁对象是方法的本地对象。正确的锁定必须使用方法范围之外的对象。
在接下来的版本中,锁定对象对于类来说是静态的,并且锁定会增加一个微小的延迟来模拟正在执行的工作。在这种情况下,应用会在方法的第二个入口处死锁。
public class Worker
private static readonly object _a = new();
private static readonly object _b = new();
private const int _delay = 5;
public Task StartAsync2( int n )
lock( _a )
Console.WriteLine( $"n: _a1 enter" );
lock( _b )
Console.WriteLine( $"n: _b1 enter" );
Thread.Sleep( _delay );
Console.WriteLine( $"n: _b1 exit" );
Console.WriteLine( $"n: _a1 exit" );
// other thread
lock( _b )
Console.WriteLine( $"n: _b2 enter" );
lock( _a )
Console.WriteLine( $"n: _a2 enter" );
Thread.Sleep( _delay );
Console.WriteLine( $"n: _a2 exit" );
Console.WriteLine( $"n: _b2 exit" );
return Task.CompletedTask;
下面是如何执行Worker
导致死锁:
var w = new Worker();
var t = new Task[5];
for( int i = 0; i < t.Length; i++ )
int n = i;
t[i] = Task.Run( () =>
Console.WriteLine( $"n start" );
w.StartAsync2( n );
Console.WriteLine( $"n end" );
return Task.CompletedTask;
);
Task.WaitAll( t );
【讨论】:
谢谢!!!我试图在 asp.net web api 控制器端点中调用Worker
,它永远不会返回响应,这意味着它是死锁,但这不会使整个应用程序死锁,我仍然可以调用另一个 api 端点。想法?
我也尝试加入后台服务,但整个应用程序没有陷入死锁或挂起的情况,API 端点仍然响应并给出 200 :(
您需要将Worker
添加到所有请求都经过的中间件管道中。当每个请求通过时,Worker
必须被调用,最终有足够的活动,应用程序将耗尽资源。【参考方案2】:
不确定 ASP.NET,根据您的代码示例,您可以尝试使用 Thread sleep / delay 之类的东西,这样每个线程就不会太快锁定资源。
大概是这样的:
lock (a)
Thread.sleep(..duration..)
lock (b)
// other thread
lock (b)
Thread.sleep(..duration..)
lock (a)
【讨论】:
对我来说看起来像代码味道,迫使这样的暂停。 是的,但因为它只是为了模拟,我认为没关系以上是关于ASP.NET Core Web API 应用程序是不是可能出现死锁或应用程序挂起状态的主要内容,如果未能解决你的问题,请参考以下文章
Asp.net core 3.1 保护 API 和 Web 应用程序
Asp.Net Core Web API 应用程序:如何更改监听地址?