Static Function Concurrency ASP.NET

后端 未结 7 1826
被撕碎了的回忆
被撕碎了的回忆 2021-02-09 18:59

If you have two threads invoking a static function at the same moment in time, is there a concurrency risk? And if that function uses a static member of the class, is there even

相关标签:
7条回答
  • 2021-02-09 19:41

    You put "ASP.NET" in the question title, this blog post is a good summary of the problems when using the ThreadStatic keyword in ASP.NET : http://piers7.blogspot.com/2005/11/threadstatic-callcontext-and_02.html

    0 讨论(0)
  • 2021-02-09 19:45

    Static methods in OO are no difference from "just" functions in procedural programming. Unless you store some state inside static variable there is no risk at all.

    0 讨论(0)
  • 2021-02-09 19:50

    Yes, there is a concurrency risk when you modify a static variable in static methods.

    The static functions themselves have distinct sets of local variables, but any static variables are shared.

    In your specific samples you're not being exposed, but that's just because you're using constants (and assigning the same values to them). Change the code sample slightly and you'll be exposed.

    Edit:

    If you call both Sum1() AND Sum2() from different threads you're in trouble, there's no way to guarantee the value of a and b in this statement: int c = a + b;

    private static int a = 5;
    
    public static int Sum1()
    {
        int b = 4;
        a = 9;
        int c = a + b;
        return c;
    }
    
    public static int Sum2()
    {
       int b = 4;
       int c = a + b;
       return c;
    }
    

    You can also achieve concurrency problems with multiple invocations of a single method like this:

    public static int Sum3(int currentA)
    {
       a = currentA;
       int b = 4;
       int c = a + b;
       int d = a * b; // a may have changed here
       return c + d;
    }
    

    The issue here is that the value of a may change mid-method due to other invocations changing it.

    0 讨论(0)
  • 2021-02-09 19:50

    Yes, there is a risk. That's why you'll see in MSDN doc, it will often say "This class is threadsafe for static members" (or something like that). It means when MS wrote the code, they intentionally used synchronization primitives to make the static members threadsafe. This is common when writing libraries and frameworks, because it is easier to make static members threadsafe than instance members, because you don't know what the library user is going to want to do with instances. If they made instance members threadsafe for many of the library classes, they would put too many restrictions on you ... so often they let you handle it.

    So you likewise need to make your static members threadsafe (or document that they aren't).

    By the way, static constructors are threadsafe in a sense. The CLR will make sure they are called only once and will prevent 2 threads from getting into a static constructor.

    EDIT: Marc pointed out in the comments an edge case in which static constructors are not threadsafe. If you use reflection to explicitly call a static constructor, apparently you can call it more than once. So I revise the statement as follows: as long as you are relying on the CLR to decide when to call your static constructor, then the CLR will prevent it from being called more than once, and it will also prevent the static ctor from being called re-entrantly.

    0 讨论(0)
  • 2021-02-09 19:55

    If the scope of the variables is contained within the static function then there is no risk, but variables outside of the function scope (static / shared) DEFINITLY pose a concurrency risk

    0 讨论(0)
  • 2021-02-09 20:00

    See here for a discussion on local variables. before your edit neither of the above methods themselves presented a concurrency risk; the local variables are all independent per call; the shared state (static int a) is visible to multiple threads, but you don't mutate it, and you only read it once.

    If you did something like:

    if(a > 5) {
        Console.WriteLine(a + " is greater than 5");
    } // could write "1 is greater than 5"
    

    it would (in theory) not be safe, as the value of a could be changed by another thread - you would typically either synchronize access (via lock etc), or take a snapshot:

    int tmp = a;
    if(tmp > 5) {
       Console.WriteLine(tmp + " is greater than 5");
    }
    

    If you are editing the value, you would almost certainly require synchronization.

    0 讨论(0)
提交回复
热议问题