Static Function Concurrency ASP.NET

2019-03-20 12:25发布

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 a bigger problem?

  • Are the two calls seperated from each other? (the function is like copied for the two threads?)
  • Are they automatically queued?

For instance in next example, is there a risk?

private static int a = 5;

public static int Sum()
{
    int b = 4;
    a = 9;
    int c = a + b;
    return c;
}

And next example, is there a risk?

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

Update: And indeed, if both functions are in the same class, what is the risk then?

thx, Lieven Cardoen

7条回答
霸刀☆藐视天下
2楼-- · 2019-03-20 12:54

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

查看更多
闹够了就滚
3楼-- · 2019-03-20 12:59

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

查看更多
我欲成王,谁敢阻挡
4楼-- · 2019-03-20 13:04

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.

查看更多
戒情不戒烟
5楼-- · 2019-03-20 13:08

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.

查看更多
成全新的幸福
6楼-- · 2019-03-20 13:11

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.

查看更多
一夜七次
7楼-- · 2019-03-20 13:14

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.

查看更多
登录 后发表回答