views:

1013

answers:

7

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

+5  A: 

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.

krosenvold
I changed first example. Now it probably isn't thread safe any more?
Lieven Cardoen
Are there good references, books, links around on this topic + how you can deal with these situations?
Lieven Cardoen
krosenvold
A last question, what if a isn't static?
Lieven Cardoen
Well then the methods accessing it couldn't be static either, and you'd have multiple threads sharing the same object instance. Same problems.
krosenvold
+1  A: 

In your two examples, there is no thread safety issues because each call to the function will have it's own copy of the local variables on the stack, and in your first example with 'a' being a static variable, you never change 'a', so there is no problem.

If you change the value in 'a' in your first example you will have a potential concurrency problem.

ScottS
True, didn't notice that Variable A is not modified, so all is good with in the code we CAN see. Potentially it could become modified outside of the visible code
Harry
Changed it. Sorry. First example wasn' that good.
Lieven Cardoen
+1  A: 

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

Harry
+1  A: 

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.

Charlie Flowers
Actually, no it doesn't *guarantee* this - you can invoke the type-initializer via reflection trivially, in which case you can call it multiple times all at once.
Marc Gravell
Ah, interesting. I never thought of that. Good point. Still, as long as you avoid calling it explicitly through reflection, you can rely on the CLR to make it threadsafe. That comes in handy sometimes.
Charlie Flowers
+1  A: 

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.

Marc Gravell
Thx. Sorry for the edit.
Lieven Cardoen
+1  A: 

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.

Sergej Andrejev
A: 

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

Matthieu