Suppose I have a class like below:
public static class Foo
{
public static int Do(int original)
{
int result=original + 1;
return result;
}
}
public class Bar
{
public void Invoke()
{
int result=Foo.Do(1);
}
}
Anyone can tell me how it be invoked in CLR? All we know that CLR is a virtual machine base on stack. An instance which would invoke Foo.Do() method has its own Call Stack. It push a int arg to Stack , and then call Foo.Do() method. I'm woudering whether few instances in multithreads invoke Foo.Do() would disturb each others? Every instance has a copy of Foo.Do() or rather?
Each thread has its own call stack set up. So when you call a function in one thread, the stack is changed only for that thread. Other threads can call whatever other functions they want, without affecting each other (aside from shared state, but that's another issue. The important thing is that the stack isn't shared).
I'm woudering whether few instances in multithreads invoke Foo.Do() would disturb each others? Every instance has a copy of Foo.Do() or rather?
In this case, each instance would be fine. There is no data shared between the separate threads, since Invoke and Foo.Do do not rely on any other shared state.
The main issues with multiple threads occur when you're trying to share data between the individual threads. At that point, you need to take care to synchronize the access to the shared data.
Perphas you should look at ThreadLocal API so you can have a thread specific storage. In your case as Reed suggested, it should not matter as there is no shared state but if there is any, it will matter as static storage is shared between threads until unless it is ThreadLocal
Related
I have a singleton client class in my solution, which calls an external service/APIs. There are no locks inside this class (nothing protecting variables being accessed by multiple threads).
If this singleton instance gets request 1, and while handling that request, it gets another request (request2). What happens? Does it continue processing request1 to completion, then serve request 2? Or will it start serving request 2 at the same time which in turn might over-write any variables in this singleton class?
Thanks for the help!
When two threads concurrently execute a method on a single instance of a class, arguments passed to a method and variables defined within that method are not overwritten. The values of fields and properties, however, can be changed.
This class is thread safe:
public class Calculator
{
public long Add(int a, int b)
{
var result = a + b;
return result;
}
}
The arguments (a, b) and the variable (result) are stored in the stack frame, memory which is allocated each time the method is executed. So the result variable exists for each method call. Two method calls cannot share or overwrite that variable.
Similarly, if this method gets called while it's already executing, the a and b arguments are not overwritten.
As a result, any number of threads can safely call the Add method on a single instance of Calculator. They can do this concurrently. One execution does not wait for the other.
This class is not thread safe:
public class Calculator
{
private int _a;
private int _b;
public long Add(int a, int b)
{
_a = a;
_b = b;
var result = _a + _b;
return result;
}
}
It's a contrived example. The difference here is that calling Add modifies the state of the class, changing the _a and _b fields. It would be the same if these were properties instead of fields.
If two threads tried to execute this at once you would get unpredictable results. Right before the first thread adds _a and _b another thread might change the value of one of those fields.
This is the simple version. There are more complicated scenarios. Suppose, for instance, we pass a List<int> as an argument to a method. If another thread has a reference to the same list, both threads could try to modify it, or one could modify it while the other is reading it, all with unexpected results. How to manage all of that is outside the scope of this answer.
Here are a few takeaways:
Don't add state to class (fields and properties that change after its constructor is called) unless it's needed. There are scenarios where we must, and in some cases it's the whole purpose of the class. But if you can choose between the examples above, always choose the first one.
Whenever we pass around references to objects like lists or instances of our own classes, consider what would happen if two threads had access to that object. And then
Don't pass them around if they're not thread safe
Make them thread safe before they're passed around
Be very, very careful. This is the worst option because it puts a burden on us and future developers to simulate the behavior of the code in our heads and see potential problems. It's so much better to prevent problems than to figure out how to navigate around them.
Another way of describing it: Concurrency is like plutonium. It's powerful and useful, but we must always know where it is and make sure it never leaks.
I have to take over the source code of a bigger application from my colleaque that is written in C#. It uses windows forms an threads and right now it works as it should.
But one thing I am not sure about, is the way he handled parameters that are used in delegates that are raised from the thread to the windows forms in the application. I don't know why, but he defined many different object arrays with varying number of elements, eg:
private object[] delegateArray1;
private object[] delegateArray3;
private object[] delegateArray3A;
and in the code he used it then
delegateArray1 = new object[1]; // in the constructor of the thread class
delegateArray3 = new object[3];
delegateArray3a = new object[3];
// and this somewhere in the thread loop
delegateArray3[0] = systemtests.FehlerText;
delegateArray3A[1] = CheckState.Unchecked;
delegateArray3A[2] = testKanal;
sender.BeginInvoke(merkerInfoDelegate, delegateArray3);
whereby sender is the containercontrol from which the thread has been created.
merkerInfoDelegate points to a method with the signature
public void InfoAnzeige(string scrollText, CheckState state, int kanal);
The first question that I have:
Is it possible that my variables / objects that I pass to the BeginInvoke method are being garbage collected and thus are invalid when the delegate method gets finally executed. When yes, how do I prevent this from happen?
Is it not possible to call the delegate like this:
sender.BeginInvoke(merkerInfoDelegate, systemtests.FehlerText, CheckState.Unchecked, testKanal);
I would like to make the code more readable, more safe and more reliable. I think of declaring classes like the class MouseEventArgs, that consist of these parameters and that encapsulate all necessary data to be passed to the delegate method in the windows forms class...
public InfoDelegateEventArgs
{
public String Fehlertext;
public CheckState state;
public int Kanal;
}
this could be used like this:
idea = new InfoDelegateEventArgs(){...};
sender.BeginInvoke(merkerInfoDelegate, idea);
It is safe to pass "local" variables but remember they are no longer "local" once you pass them. The references have now been passed off to another operation that may be running concurrently on a separate thread. Now multiple threads have access to the "local" variable and thus it might require locking or other thread-safe treatment.
You don't need to worry about it being GC'd because there is still a reference that was passed to BeginInvoke.
If I define an object like a logger object as static in a class, then call a method like the following:
public class Manager
{
private static ClientLogManager log = new ClientLogManager();
public void Log(string Message)
{
log.Debug(string Message);
}
}
This is defined in a class library project.
My understanding is that the static variable is shared between all requests for this application, so the log object is shared. However the method Debug itself is not static, but the object is static, so there will be only one instance of this method. Is that correct?
If a lot of users are calling this code at the same time, if 2 requests are calling the log.Debug method at the same time, can the message of the 2nd request overwrite the message of the 1st request?
Also, is it better to replace this with a Singleton? wouldn't it be one Singleton object per request?
Here is the ClientLogManager code
public class ClientLogManager
{
#region Member Variables
private static readonly ILog _log = LogManager.GetLogger(typeof(ClientLogManager));
#endregion
#region Constructors
public ClientLogManager()
{
}
#endregion
#region Public Methods
public void Debug(string message)
{
_log.Debug(message);
}
#endregion
}
If a lot of users are calling this code at the same time, if 2 requests are calling the log.Debug method at the same time, can the message of the 2nd request overwrite the message of the 1st request?
Yes, unless the logger is specifically written to support this. Most loggers are designed to support this, so unless you rolled your own from scratch chances are it will synchronize all writes internally (so that you don't have to). If you are unsure you should check the documentation for the specific logger you are using to see if it will support or break when written to simultaneously.
"My understanding is that the static variable is shared between all requests for this application, so the log object is shared."
Correct, there exists only 1 instance of a static member per AppDomain.
"However the method Debug itself is not static, but the object is static, so there will be only one instance of this method. Is that correct?"
The statement in itself is correct, but...
What it boils down to is this:
Both static and instance methods "exist" only once in memory, the difference is that
a static method does not need an instance of the class it's declared on in order to
be executed, whereas an instance method does.
If multiple requests can be handled concurrently, they have to be executed on different
threads. Each thread has its own call stack, and if you use a thread to perform a method
call on, the arguments passed to that method are placed on the call stack of that thread.
This means that, as long as the argument is either a valuetype (such as an int) or an
immutable type (such as in this case, a string) it cannot be modified by another thread
(because it is either not visible from another thread, or not modifyable).
Hence, you don't have to worry that the messages get mixed up inside your Manager.Log() or ClientLogManager.Debug() method.
So, both your current Manager and ClientLogManager implementations are thread-safe (at least, if the _log instance is thread-safe).
Once you start declaring non-static member variables in your Manager class, and
you're going to use them in Manager.Log(), then it is no longer thread-safe:
The same Manager instance could then be accessed by multiple threads, and once they
all start writing in the same member variable, you're in trouble...
I hope this clarifies things a bit.
Static fields are being accessed using the class name like this:
public class Me()
{
public static int a=5;
}
I can access it with Me.a, so it is attached to the class.
But when I look at:
static ThreadLocal<int> _x = new ThreadLocal<int> (() => 3);
It guarantees that each thread sees different copy of _x.
Didn't we just see that static is per class and not per thread? How does ThreadLocal manage to give each thread a different copy of _x?
Didnt we just see that static is per class and not per thread ?
Yes. So imagine that a ThreadLocal<T> instance holds a static Dictionary<Thread, T> that looks up the Value for the current thread.
That is probably not how it actually works but it's a simple explanation of how it's possible. You could write it yourself.
So you still have only 1 static _x. But _x.Value can be bound to anything, like the courrent Thread.
The reference _x will indeed be one per class, as per its static specifier. However, only the reference will be shared among all threads, not the value inside its object. When you access _x.Value, ThreadLocal<T> invokes system-specific code that provides storage on the current thread, and reads or writes to that thread-specific storage.
My C# isn't that great, so here's a C++ answer to the same effect: Imagine a hypothetical class that contains a large array:
class Foo
{
int array[HUGE];
int & get() { return array[this_thread_id()]; }
}:
Now you can have one single, global (or class-static) object:
Foo tlstorage;
To access it from anywhere you say tlstorage.get() = 12;. However, the data is stored in the slot that "belongs" to your current thread. The entire storage is global, but only one slice is exposed to each thread.
Other languages like C and C++ have native support for this concept, and when you decorate a global or static variable as "thread-local", the compiler builds something that amounts to the same effect automatically. Perhaps in C# this is a library feature, though it probably also maps to something intrinsic.
Theoretical question.
If you have 100 separate requests coming to an aspx web page that calls the static method below.
public static GeocodeResult GeocodeQuery(string query)
{
int train, tube, dlr = 0;
// manipulate these ints
if (train)
{
// do something important
}
}
Does every request have a separate call stack?
If so -
Does this static method call get pushed on these separate call stacks?
If so -
Therefore are these ints thread safe? ie. 100 requests, 100 call frames, 300 ints.
Cheers
Yes, each request has it's own call stack. And each stack will contain it's own values for query, train, tube, dir, since local variables and method parameters are stored in stack.
So, unless you are accessing some shared state, this method is thread safe.
All static methods are thread safe if the only variables it uses are local variables or parameters.
Note that it's not that a method has a call stack - a thread has a call stack. Methods are invoked by a thread.
Unless the method is inlined, invoking it may push parameters onto the call stack, but will definitely push the return address onto the call stack.
Each thread call stack is independent of the call stack of any other thread. If only the stack is accessed, then the method is thread-safe.
Other storage could be accessed to make the method not thread-safe. That includes static data and instance data as well as objects referenced by them. A static method has no access to instance data, which makes it easier for it to be thread-safe. You only need to watch out for access to static data, or objects referenced by static data:
private static int _balance;
private static void ThreadSafetyIssues()
{
// Not thread safe
int temp = _balance;
temp ++;
_balance = temp;
// Not thread safe
temp = (int) HttpContext.Current.Session["balance"];
temp ++;
HttpContext.Current.Session["balance"] = temp;
}
The HttpContext.Current property is static. This means that any thread can access the context at the same time, including Session. This is just as non-thread-safe as the simple static _balance field above.