views:

307

answers:

6

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?

+4  A: 

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.

btreat
You don't need to introduce locking necessarily. You can do some pretty fancy things with System.Threading.Interlocked.*.
Spence
Another, perhaps easier, way to make that assertion is to mark all instance variables `readonly` to make the class immutable.
Martin Wickman
+4  A: 

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.

Martin Wickman
I disagree with you on 2 reasons.1. There are different kinds of immutability which we work with. http://blogs.msdn.com/b/ericlippert/archive/2007/11/13/immutability-in-c-part-one-kinds-of-immutability.aspx2.'final' is Java, you mean make them constants ? If yes, I disagree. Making all the fields in the class constants is a lot different from making them threadsafe
ram
Being immutable is useless when you need threads to actually share data (which I'm asssuming is the case based on the question).
Gabe
By final I mean _make sure it has a value after the constructor, and that value is read only once assigned_. There are lots of examples out there, proving my point, ie http://blogs.msdn.com/b/lucabol/archive/2007/12/06/creating-an-immutable-value-object-in-c-part-ii-making-the-class-better.aspx http://pebblesteps.com/post/Introduction-to-Immutability-in-C.aspx
Martin Wickman
Marking fields `readonly` is not enough to guarantee thread-safety. What if they are references to other objects, which are manipulated internally by the class (in ways not obvious to the caller) and are themselves not thread-safe? The `readonly` keyword won't prevent their state from being corrupted.
Evgeny
The answer is not helpful. All thread safe classes can't be immutable, can they? locking is the way to go
jgauffin
@jgauffin, I don't share your opinion. Thread safety is quite a complex topic, and making classes immutable where appropriate is indeed one step in that direction. Just need to repeat Evgeny's words: What about references to other classes? If you want your class to be thread-safe, you need to make sure that they are thread-safe, too - OR immutable. Of course, immutability is not enough, but its one part of the solution. Take strings, e.g., I would claim that thread safety was one of the major reasons (besides memory) that led to the decision to make them immutable.
chiccodoro
My point was that locking is more common than immutable objects. You can't get very far if you only know about immutable objects. Knowing about just locking will take you... "What about references to other classes": One has to make sure that the called classes are thread safe too. I don't see that as a big issue as long as you know about it.
jgauffin
It goes without saying that you cannot expect threading to work in mutable parts of the system. You need locking/synchronization in those parts. Please don't repeat that argument again. Hmm... it seems people are new to this. I would encourage you to spend some time looking into languages that has immutability as it's core (Scala for instance) and what the implications are. You see, one major selling point for these languages is thread safety and scalability due to immutability. That cannot be disputed.
Martin Wickman
A: 

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

ram
A: 

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.

Gabe
A: 

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.

jgauffin
A: 

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.

Lasse V. Karlsen