May somebody please point me the pros and cons on using static methods or any URL where I can read about them? I've read static fields and objects may be a problem in multithreaded environments so far, but nothing about static methods. Also, I think there are memory "disadventages" when using static data (like they are alive all the time the application is running), but I'm not sure about static methods. Do you know about a site I can find information about this topic?
Thanks in advance!
Do you know why static members are bad in multithreaded app? For similar reason static methods are bad too.
Basically if you run a static method from several threads at the same time they all share the same code and local variables. That means if two threads run a loop from 1 to 10000 concurrently the loop variable will not go from 1 to 10000 in steps of one for both threads.
Do you mean local variable 'number' in this piece of code is "shared" by all application threads?
public static void DoSomething() { ... int number; // non-static variable ... }
I don't think so. Maybe you are talking about static local variables. If I don't use static variables, just static methods with non-static local variables, it shouldn't be a problem. Am I right?
I don't have time to test things right now but I might get time in about 8-10hrs.
I haven't done threaded programming for a while and I might have been wrong.
It should be quite simple to test, actually.
Just create a function like this and run it in several threads in parallel:
public static void DoSomething(int threadId) { int number=threadId; // non-static variable /* do stuff for a while */ if (number!=threadId){ //I was correct } }
In that code, the parameter threadId should be different for each thread that runs that function.
Of cource you should run that function for several millions of times, especially if your PC can't run two threads simultaneously. If you have more than one (virtual*) CPU then the problem should show much sooner.
*) Intel HT or any other CPU supporting SMT.
As I understand it, each thread has its own stack, and non-static local variables are put on the stack, therefor non-static local variables can be different across threads. The heap, however, is 100% shared, so writing something on the heap will effect other threads (static local variables and globals, and dynamicly allocated memory is all on the heap). Exactly how variables will be effected is completely undefined.. it'd depend on the compiler, assumptions the compiler makes when optimizing, etc. That's the reason why variables used in Allegro timers need to be marked volatile, so the compiler won't make the assumption that they won't change unexpectedly, because they may.
Of course, this is using my knowledge of C/C++. No idea if C# is different.
I concur with the Kitty. Those things are created on the stack, so static methods are safe.
Globals, static variables, or just any plain old variable can be dangerous in a multithreaded environment, but only when they can be accessed at the same time by more than one thread, and are not locked during that accessing. A couple mutexes fixes that, or C# might have some built-in language features to accommodate such things, like "synchronized" in Java.
EDIT: Be careful with any "synchronized" features, though. I must say, while synchronized is a blessing in Java, it'll kill you if you don't understand what it's doing and why. It seems so simple, just a couple letters and a once dangerous multithreaded environment is safe from harm, but in reality it is just as dangerous!
What I'm trying to say is that if you don't understand multithreading and its problems ... stay away from it! Synchronized and synchronized-like features are meant to ease the lives of experts; they do not help a beginner.
***Replace "synchronized" with whatever C# uses.
Basically static methods are "bad" because if you need to remove the staticness, then the refactoring task would be enormous. Plus in a multithreaded context you need to lock the shared context.
Of course I have never seen an app without globals; somewhere the app should have its data.
Only static methods can access static members, so if thread safety of static variables is an issue, use critical sections. I don't know about C#, but in Java that would involve synchronising the whole static method. In some cases, if the static member that needs thread safety is an object, you can get away with just synchronising on that object for the necessary critical section (instead of synchronising the whole static method).
As for local and member variables, they are all shared when two or more threads enter the same object. So any variable access should be locked down with critical sections. In Java, it's a simple matter of using a synchronized (this) { ... } block.
As for refactoring by removing the staticness, I disagree. I've never come across this situation. If something changes from static to non-static, I would assume that this is only a small part of some major reworking that superficial refactoring doesn't suit anyway.
IMO, multithreaded apps or not, static variables("globals") should be avoided where possible any only used if the situtation warrants it. Besides the thread-safety issues, code that uses statics/globals is very difficult to test and validate. For example a method like sqrt is extremely trivial to test. However, a method like OpenGL's glColor3f is harder to test because it relies on and changes globals.
I think almost all questions like this really are referring to the concept of "intellectual scope." By intellectual scope I am meaning the number of things your mind has to keep track of in order to verify that a piece of code is correct. Global variables increases that scope.
That said, static methods -- there is no problem there. For example, it makes perfect sense that a method like sqrt, where the entire "scope" of the function is limited to its parameters and return value, is fine.
Also, by global, I mean more than just simply a global variable -- I also mean any global "context". For example consider the following functions:
writeConfigFile() -- Reads configuration from global Config variables and writes to a file specified in the registry key HKCU/software/whatever
writeConfigFile( Config c ) -- writes configuration given to a file specified in the registry
</li>
In each example, the scope is "reduced" and the methods are easier to test and therefore I would consider them "better" design as you go down the list. Think of how you would test the method with no parameters -- it relies on a set of global variables, which are not necessarily easy to set up. It also relies on the state of the registry of the computer it is running on. To test it you'd have to write registry keys and also execute a ton of unrelated setup code.
If it is not apparent already, to tie this back into the threading discussion, the third method is also more naturally thread-safe since you can give it its entire state -- it doesn't have to worry about other threads accessing the global configuration or registry, because its "scope" has been reduced.
Static anything just means 'relating to the class rather than the object' - there isn't anything bad about using them in multithreaded applications except when they more than 1 thread accesses the same data, static or not. The static functions are the same as normal functions.