One of the many merits of local variables: avoiding race conditions

Another little piece of advice to my coworkers…

Here’s a quick tip about using local variables that might reduce your multithreading headaches, at least a little bit.

Developers often think of locally cached variables as useful in one of two ways:

  1. Small performance optimizations (in cases where the cached value replaces redundant method calls)
  2. Readability improvements

Well, there’s another way in which local variables are useful (you may already know this; but you may not, which is why I’m mentioning it): avoiding race conditions.

Obviously, not all race conditions. But certain race conditions, particularly those that can potentially result in a nasty NullReferenceException, can be handily evaded with the assistance of local variables.

Here’s a simple example:

For Each x In GlobalCollection.Items
    ' Do something with x.

Never mind (for now) any other issues you might notice in the above code. I just want to focus on the issue at hand.

Let’s say the above is susceptible to a NullReferenceException in certain cases, where it may be called before GlobalCollection is initialized (or after it’s set to Nothing, for whatever reason).

One attempt to “fix” this error might be to do this:

If GlobalCollection IsNot Nothing Then
    For Each x In GlobalCollection.Items
        ' Do something with x.
End If

Now, the truth is that the above “fix” will probably work about 90% of the time. But it’s really just a ticking time bomb, waiting to blow up at what is almost certainly going to be a very bad time. The reason is that, if GlobalCollection might be set to Nothing on a separate thread, this could happen between when the above code checks If GlobalCollection IsNot Nothing and the following line.

Here’s a superior fix, which is not susceptible to this race condition:

' Here we declare a local variable that is set to whatever object
' GlobalCollection (the field or property) references at this
' moment.
Dim localCollection = GlobalCollection

' Now, even if GlobalCollection is set to Nothing, localCollection
' still has a reference to the object it was previously pointing
' to. It's impossible for some external thread to infiltrate this
' local stack frame and change localCollection; therefore once we
' check localCollection IsNot Nothing, we can rule out the
' possibility of a NullReferenceException.
If localCollection IsNot Nothing Then
    For Each x In localCollection.Items
        ' Do something with x.
End If

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )


Connecting to %s

%d bloggers like this: