代码之家  ›  专栏  ›  技术社区  ›  user584018

ASP是否可能处于死锁或应用程序挂起状态。NET核心Web API应用程序

  •  2
  • user584018  · 技术社区  · 2 年前

    我有一个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中的任何一个都不会给出任何200的结果?

    谢谢

    0 回复  |  直到 2 年前
        1
  •  2
  •   Metro Smurf    2 年前

    如所写,当前方法将 从未 僵局

    锁定对象是该方法的本地对象。正确的锁定必须使用方法范围之外的对象。

    在下面的修订版中,锁定对象对类是静态的,并且锁定添加了一个微小的延迟来模拟正在执行的工作。在这种情况下,应用程序将与方法的第二个入口死锁。

    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 );
    
        2
  •  0
  •   Raymond Hartoyo    2 年前

    不确定ASP。NET中,基于您的代码示例,您可以尝试使用诸如线程睡眠/延迟之类的东西,这样每个线程就不会过快地锁定资源。

    可能是这样的:

            lock (a)
            {
                Thread.sleep(..duration..)
    
                lock (b)
                {
                }
            }
    
            // other thread
            lock (b)
            {
                Thread.sleep(..duration..)
    
                lock (a)
                {
                }
            }