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
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
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
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;
You can also achieve concurrency problems with multiple invocations of a single method like this:
The issue here is that the value of a may change mid-method due to other invocations changing it.
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:
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:If you are editing the value, you would almost certainly require synchronization.
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.
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.