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

我能把退货声明放在锁里吗

  •  15
  • DevinB  · 技术社区  · 15 年前

    笨蛋: return statement in a lock procedure: inside or outside

    标题有点误导人。我知道你可以做到,但我想知道性能的影响。

    考虑这两个代码块。(无错误处理)

    这个街区有 return 锁外

     public DownloadFile Dequeue()
     {
         DownloadFile toReturn = null;
         lock (QueueModifierLockObject)
         {
             toReturn = queue[0];
             queue.RemoveAt(0);
         }
         return toReturn;
     }
    

    这个街区有 返回 陈述 在内部

     public DownloadFile Dequeue()
     {
         lock (QueueModifierLockObject)
         {
             DownloadFile toReturn = queue[0];
             queue.RemoveAt(0);
    
             return toReturn;
         }
     }
    

    代码有什么不同吗?我理解性能差异(如果有的话)将是最小的,但是我特别想知道在 lock 得到释放。

    3 回复  |  直到 15 年前
        1
  •  24
  •   Andrew Hare    15 年前

    C编译器将把返回语句移到 try/finally 它是为 lock 声明。就编译器将为它们发出的IL而言,这两个示例是相同的。

    下面是一个简单的例子,证明:

    class Example
    {
        static Object obj = new Object();
    
        static int Foo()
        {
            lock (obj)
            {
                Console.WriteLine("Foo");
                return 1;
            }
        }
    
        static int Bar()
        {
            lock (obj)
            {
                Console.WriteLine("Bar");
            }
            return 2;
        }
    }
    

    上面的代码编译为:

    internal class Example
    {
            private static object obj;
    
            static Example()
            {
                    obj = new object();
                    return;
            }
    
            public Example()
            {
                    base..ctor();
                    return;
            }
    
            private static int Bar()
            {
                    int CS$1$0000;
                    object CS$2$0001;
                    Monitor.Enter(CS$2$0001 = obj);
            Label_000E:
                    try
                    {
                            Console.WriteLine("Bar");
                            goto Label_0025;
                    }
                    finally
                    {
                    Label_001D:
                            Monitor.Exit(CS$2$0001);
                    }
            Label_0025:
                    CS$1$0000 = 2;
            Label_002A:
                    return CS$1$0000;
            }
    
            private static int Foo()
            {
                    int CS$1$0000;
                    object CS$2$0001;
                    Monitor.Enter(CS$2$0001 = obj);
            Label_000E:
                    try
                    {
                            Console.WriteLine("Foo");
                            CS$1$0000 = 1;
                            goto Label_0026;
                    }
                    finally
                    {
                    Label_001E:
                            Monitor.Exit(CS$2$0001);
                    }
            Label_0026:
                    return CS$1$0000;
            }
    }
    

    如您所见,编译器已经自由地将RETURN语句移入 Foo 在外面 尝试/最终 .

        2
  •  2
  •   Charles Bretana    15 年前

    我相信IL是一样的…我必须测试它才能确定,但是lock语句在il中生成了一个try finally,并且返回将在堆栈帧关闭并返回给调用方之前触发finally(和release),所以…

        3
  •  0
  •   Philip    15 年前

    是的,但是为什么不使用出列呢?

    记住,lock只是以下几行的简写:

            try
            {
                Monitor.Enter(QueueModifierLockObject);
    
                DownloadFile toReturn = queue.Dequeue();         
    
                return toReturn;
            }
            finally
            {
                Monitor.Exit(QueueModifierLockObject);
            }