泛型类型或类型对象的参数,线程安全吗?

时间:2017-02-06 23:51:20

标签: c# generics static thread-safety webmethod

   [Webmethod]

     Public static string GetAge(List<int> input1, string input2)
     {
     Cust cu=Cust.CalAge(input1,input2)
     cu.agemodify=true;

     }

AJAX调用调用此Web服务。

CalAge是类Cust内的静态方法。

agemodify是班级boolean内的Cust字段。

  1. 我知道所有非静态字段/局部变量都有 即使在静态方法中,每个线程的堆栈上也有不同的副本。是 那是对的吗?所以这些是线程安全的,不是共享资源。 因此,agemodify是线程安全的吗?
  2. 我的理解是List<int>是线程安全的参数 对于静态方法,因为对于int,不可变性不适用。是 那是对的吗?我知道list <T>不是线程安全的。怎么样呢 如果T是不可变的,则<T>s作为参数;如果是T,则作为参数 一成不变的?例如public static int GenMethod<TFirst,TSecond>(), GetMethod(List<object> o1, object o2). Just Object vs List<Object>.我不想使用System.Collections.Concurrent。
  3. 我的理解是因为Webmethod是静态的,任何类 无需实例化堆栈,因此, 也许是静态的,因为只有一个Webmethod 整个“实例”。那是对的吗?有一个是更好的 专用的webservice(wcf / asmx)wrt线程安全而不是静态 aspx页面上的webmethods?

1 个答案:

答案 0 :(得分:2)

不幸的是,你的问题接近于过于宽泛。你似乎把几个不同的和完全不相关的概念混为一谈,好像它们以某种有意义的方式相互联系,即使它们不是。我怀疑在Stack Overflow回答的上下文中,有可能解开这里表达的所有误解。

那就是说,我试一试。至少,我希望通过以下内容,您可以返回足够的信息来查看主要来源(例如MSDN,其他文档)并更正您的理解。在最好的情况下,也许下面的内容足以让你完全回到正轨。

  
      
  1. 据我所知,即使在静态方法中,所有非静态字段/局部变量在每个线程的堆栈上都有不同的副本。那是对的吗?所以这些是线程安全的,不是共享资源。因此,agemodify是线程安全的吗?
  2.   

&#34;这是正确的吗?&#34; - 不是。这是边缘的胡言乱语。在方法中声明的局部变量具有新实例,因此在方法中传递或初始化任何值的新副本,用于对方法的每次调用。所以,在局部变量的情况下,每次在不同的线程中调用方法时,都有新的副本,但这与线程无关。这完全是关于方法调用的。

对于非静态字段,这些可能会也可能不会存储在堆栈†上,因此任何基于它们存储在堆栈中的假设的结论都是错误的。对于引用类型,您只能为该对象的每个实例获取一个新副本。对于值类型,您还会为每个值类型实例获取每个字段的新副本,但由于每次将其分配给新变量时都会获得值类型的新实例,因此可能会有很多更多副本。但同样,与线程无关,与堆栈无关(因为值类型可以存在于堆栈上的堆栈中)。

&#34; agemodify因此是线程安全的?&#34; - 没有足够的代码来回答这个问题。您需要为任何人提供一个好的Minimal, Complete, and Verifiable code example来明确回答。如果Cust类型是引用类型,则 CalAge()方法始终会创建该类型的新实例,或者Cust类型是值类型,然后我会说是的,该字段是线程安全的。

否则,不一定。

†就此而言,局部变量存储在堆栈上只是一个实现细节。对于常规局部变量,它不太可能改变,但C#中没有要求它们以这种方式处理。它们可以存储在任何地方,只要编译器保留局部变量的语义,实际上这正是C#中各种上下文中发生的事情,例如捕获的局部变量,以及迭代器方法等特殊方法中的局部变量。和async方法。

  
      
  1. 我的理解是List<int>作为静态方法的参数是线程安全的,因为int不变性不适用。那是对的吗?我知道List<T>不是线程安全的。如果T是不可变的那么只有<T> s作为参数呢?如果它们是不可变的那么对象呢​​?例如public static int GenMethod<TFirst,TSecond>(),   GetMethod(List<object> o1, object o2)。只需Object vs List<Object>。我不想使用System.Collections.Concurrent
  2.   

同样,所有这些都没有任何意义。作为局部变量的input1变量的值本质上是线程安全的,因为每次调用该方法都存在一个新副本。但那只是变量。 List<int>对象本身完全不受此影响,并且显然线程安全。只有当执行该方法的每个线程获得List<int>对象的唯一实例时,才能说这是线程安全的。

对于类型参数T的值,没有任何关于泛型会使这些本质上是线程安全的。就线程安全而言,T只是另一种类型。在编译泛型类型或方法时,您不知道类型的事实是无关紧要的,并且不以任何方式帮助使该类型的值成为线程安全的。

  
      
  1. 我的理解是因为Webmethod是静态的,所以堆栈中的任何类都不需要实例化,因此,也可能是静态的,因为只有一个Webmethod&#34;实例&#34;始终。那是对的吗?在aspx页面上使用专用的web服务(wcf / asmx)和线程安全而不是静态web方法更好吗?
  2.   

对不起,更多的是无意义的单词组合。什么是&#34;类进一步向下堆栈&#34; ?例如,如果您调用需要使用string值的方法,您是否真的认为这意味着您可以使用static类型的神秘string版本,因为来电是静态的?

不,关于需要static的内容以及与调用者没有多大关系的规则。调用者唯一影响的是非静态调用者不需要提供显式实例引用来在同一个类中使用其他非静态成员,因为那里有该上下文中的隐式this引用。否则,调用实例成员的static方法仍需要实例引用。如果您可以让static方法使用的成员也是static,那就更好了,因为那样您就不必提供该实例。

但仅仅因为调用方本身是static,而 意味着您无法在调用上下文中实例化对象。如果您需要访问某种类型的实例成员,您仍然需要该类型的实例。

就Web服务特定的内容而言,这完全取决于方法中使用的值的性质。你的问题中没有足够的背景来提供关于此的任何形式的明确讨论。