繁体   English   中英

在同时调用方法时是否需要同步访问方法参数和本地?

[英]Do I need to synchronize access the method arguments and locals when calling a method concurrently?

我一直在用静态类/方法编写很多代码,我认为这些代码将由多个线程同时调用/执行。 所以我在我的方法中做了很多锁定。 我通常这样做:

public static class MyThreadsafeMethods {

    private static Object staticLock1 = new Object();
    private static Object staticLock2 = new Object();

    public static string StaticMethod1(string param1, int param2) {
        lock (staticLock1) {
            var _param1 = param1;
            var _param2 = param2;

            //highly confidential business logic here

            return StaticMethod2(_param1, "Integer: " + _param2.ToString());
        }
    }

    public static string StaticMethod2(string param1, string param2) {
        lock (staticLock2) {
            var _param1 = param1;
            var _param2 = param2;

            //truly groundbreaking algorithm here

            return _param1 + " - " + _param2;
        }
    }
}

我想知道两件事:

1)我以为我需要在“锁定代码”中使用我的参数的本地“副本”; 因为如果另一个线程用param1和param2的不同值调用我的方法,那可能会搞砸我的处理。 如果我只使用在锁定代码中声明/实例化的变量(即上例中的_param1和_param2),那么某些东西可以改变param1和param2的值(或者发送对不同对象的引用),我没关系。 但我需要这样做吗? 我是不必要的偏执狂?

2)我已经决定在我需要它之前不想实例化我的锁对象,因为我的静态锁定对象集合正在增长......所以,我现在正在这样做:

    private static Object staticLock1;

    public static string StaticMethod1(string param1, int param2) {
        lock(staticLock1 = staticLock1 ?? new Object()) {
            (...)
        }
    }

是否有任何理由在我第一次需要时实例化我的锁定对象是不安全的? 在我的锁定语句中使用我的锁定对象上的赋值运算符会不会导致我出现问题或阻止对象被正确锁定?

  1. 你所拥有的东西根本没有任何区别 - 在调用之后,参数本身不会改变,所以它什么也没做。 在你的情况下使用字符串,看到字符串是不可变的是非常安全的。 如果不是这种情况,则传递的任何内容都可能在其他地方被更改。 在这种情况下,你必须制作一个真正的副本(即不只是复制参考),

  2. 考虑两个线程同时到达lock(staticLock1 = staticLock1 ?? new Object())的情况。 他们都可以将staticLock1视为null。 所以没有那不安全!

您的主要困惑似乎是为了安全地同时安全地调用静态方法所需的同步。

数据争用总是会出现,因为多个线程以不同步的方式访问同一个存储位置,并且其中至少有一个是编写器。 这个基本规则足以说明很多并发问题。

调用方法时,参数对每个调用都有不同的存储位置。 他们是独立的。 因此,调用相同方法的两个线程永远不会竞争访问方法参数。 因此,您永远不需要同步对方法参数的访问。

当地人也是如此。 实际上,参数具有与locals相同的同步属性。 每次通话都存在。

回答你的第二个问题:这是不安全的,因为两个线程可能会锁定不同的对象。 此外,您在多个线程上写入staticLock1同步。 我已经解释过这是一场数据竞赛。

第一:创建Object实例的开销非常小。 除非测量显示您应该这样做,否则不要担心。

只需像这样初始化:

private readonly static object staticLock1 = new Object();

你使用lock语句的方式并不安全。

其次:我在方法中看不到共享数据,所以没有理由锁定。

最后:如果设计包含许多静态函数,我会重新考虑它。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM