When reading the MSDN documentation it always lets you know if a class is thread safe or not. My question is how do you design a class to be thread safe? I am not talking about calling the class with locking I am meaning I am working for Microsoft create XXX class\object and I want to be say it is "Thread Safe" what would I need to do?
To state that the class is thread safe, you are assserting that the internal data structures in the class won't be corrupted through concurrent access by multiple threads. To make that assertion, you would need to introduce locking (synchronize in Java) around critical sections of code within the class which could potentially lead to corruption of they were executed by multiple concurrent threads.
The easiest and most foolproof way of making a class thread safe is to make it immutable. The beauty of it is that you don't ever have to bother with locking again.
Recipe: Make all instance variables readonly
in C# (final
in Java).
- An immutable object, once created and initialized in the constructor, cannot change.
- An immutable object is thread safe. Period.
- This is not the same as having a class with only constants.
- For mutable parts of your system, you still need to account for and handle locking/synchronization property. This is one reason to write immutable classes in the first place.
See this question as well.
non generic ICollection
classes provide properties for thread safety. IsSynchronized and SyncRoot. unfortunately you cannot set IsSynchronized. You can read more about them here
In your classes you can have something simlar to IsSynchronized and Syncroot , expose public methods/properties alone and inside method body check for them. Your IsSynchronized will be a readonly property, so once your instance is initialized, you will not be able to modify it
bool synchronized = true;
var collection = new MyCustomCollection(synchronized);
var results = collection.DoSomething();
public class MyCustomCollection
{
public readonly bool IsSynchronized;
public MyCustomCollection(bool synchronized)
{
IsSynchronized = synchronized
}
public ICollection DoSomething()
{
//am wondering if there is a better way to do it without using if/else
if(IsSynchronized)
{
lock(SyncRoot)
{
MyPrivateMethodToDoSomething();
}
}
else
{
MyPrivateMethodToDoSomething();
}
}
}
You can read more about writing thread safe collections on Jared Parson's blog
The documentation doesn't suggest that classes are thread-safe, only methods are. In order to assert that a method is thread-safe, it has to be callable from multiple threads simultaneously without giving incorrect results (where incorrect results would be the method returning the wrong value or the object getting into an invalid state).
When the documentation says
Any public static (Shared in Visual Basic) members of this type are thread safe.
it probably means that the static members of the class do not mutate shared state.
When the documentation says
Any instance members are not guaranteed to be thread safe.
it probably means that methods have minimal internal locking.
When the documentation says
All public and protected members of this class are thread-safe and may be used concurrently from multiple threads.
it probably means that all methods you can call use the appropriate locking within them. It is also possible that the methods do not mutate any shared state, or that it is a lock-free data structure that by-design allows concurrent usage without any locks.
Thread safe classes is all about protecting the data (instance variables) in your class. The most common way to do that is to use the lock keyword. The most common newbie mistake is to use lock the entire class instead of a more finegrained lock:
lock (this)
{
//do somethnig
}
The problem with that is that it can give you a major performance hit if the class does something important. The general rule is to lock as little as possible as short time as possible.
You can read more here: http://stackoverflow.com/questions/59590/lock-keyword-in-c
When you have strarted to understand multithreadnig more deeply you can also take a look at ReaderWriterLoch and Semaphore. But I suggest you only start with the lock keyword.
In addition to the other excellent answers here, consider another angle as well.
It isn't enough that the internal data structure of the class is 100% thread safe if the public API has multi-step operations that cannot be used in a thread-safe manner.
Consider a list class that has been built such that no matter how many threads are doing no matter how many types of operations on it, the internal data structure of the list will always be consistent and OK.
Consider this code:
if (list.Count > 0)
{
var item = list[0];
}
The problem here is that between the reading of the Count
property and the reading of the first element through the [0]
indexer, another thread might have cleared out the contents of the list.
This type of thread safety is usually forgotten when the public API is created. Here, the only solution is for the calling code to manually lock on something on each such type of access to prevent the code from crashing.
One way to solve this would be for the list type author to consider typical usage scenarios and add the appropriate methods to the type:
public bool TryGetFirstElement(out T element)
then you would have:
T element;
if (list.TryGetFirstElement(out element))
{
....
presumably, TryGetFirstElement
works in a thread-safe manner, and would never return true
at the same time as it is not able to read the first element value.