Lock-free state pattern in C#

Summary: I describe a pattern for fast code, which is logically easy to understand, and can help avoid deadlocks in concurrent C# programs.

I like to avoid using the lock statement in C# for short bits of code that don’t block. This is partly based on an only loosely supported idea that Interlocked operations are faster for simple code. I often use the concept of a protected immutable state object as an inner class of my object. Then, my objects have only one mutable member variable if mutability seems necessary. To update the state, I use code like this:

State state = _state;
State old_state;
State new_state;
do {
old_state = state;
new_state = SomeFunction(old_state, arg1, arg2, arg3);
state = Interlocked.CompareExchange<State>(ref _state, new_state, old_state);
}
while( state != old_state);

The above code works logically as: read the state, compute the new state based on the old state, and then, if the state is still the same as it was when we did our computation update it. CompareExchange returns the value of _state when it is called, so by looking at the result we can see if we were successful, or if we need to try again.

I could encapsulate this pattern as:


class Mutable<StateT> {
protected StateT _state;
public StateT State { get { return _state; } }
//Use the delegate how_to_update to map the
//old state onto the new state and return the new state
public StateT Update(System.Converter<StateT, StateT> how_to_update) {
StateT state = _state;
StateT old_state;
StateT new_state;
do {
old_state = state;
new_state = how_to_update(old_state);
state = Interlocked.CompareExchange<StateT>(ref _state, new_state, old_state);
}
while( state != old_state);
return new_state;
}
}

Since delegates can (or at least once did) have performance issues, it doesn’t make a lot of sense to do the above for highly performance critical code, but of course, one should only obsess about that if benchmarking shows that a particular usage is causing problems.

The above statement may call into question the whole approach: why not just update _state in a lock? One reason is that the above code can never deadlock since how_to_update is not holding a lock when it is being called. Of course, you can do the same logic as CompareExchange with a lock, but at that point, why not just CompareExchange?

4 comments

  1. james Aug 15

    well I cant get it to compile with my code :s

  2. Anime games Sep 10

    And now I’m missing programming because of this post, I have to say you inspired me again to touch .NET but the increase of popularity in web technologies make me concentrate to PHP I’ll follow your blog from now on but I think it needs updating.^^ More power to you sir

  3. Queensland Oct 4

    Would you mind uploading the same but in C++?
    Thanks anyways.

  4. Small Business Help Oct 5

    I remember, a C# course I took in college. The problem was our teacher insisted on us using the GUI. Not really the best way to learn. I’ve since dropped it, but am focusing on PHP.

Leave a reply