Multithreading: using the volatile in your C# code
Today we’re only going to talk about the volatile keyword. The volatile keyword can be used on the declaration of a field, transforming it into a volatile field. Currently, you can only annotate a field with this keyword if it is:
- a reference type;
- a pointer type (unsafe code);
- one of the following types: sbyte, byte, short, ushort, int, uint, char, float or bool;
- an enum with a base type of byte, sbyte, short, ushort, int or uint.
As we’ve seen, volatiles ensures that proper fences are applied when someone access that field (ie, reading means having an acquire fence and writing ends up injecting a release fence). As you know by now, load and store reordering can happen at several levels and you might be wondering if using the volatile is enough for ensuring that fences are applied on all levels. Fortunately, the answer is yes, and the volatile keyword is respected by the compiler and by the processor.
Ok, so when should you use this keyword? Well, probably an example is in order, right? Lets take a look at the following code which shows the code I’ve written in the past for lazy loading:
class Lazy {
private SomeObject _object;
private Object _locker = new Object();
public SomeObject SomeObject {
get {
if (_object == null) {
lock (_locker) {
if (_object == null) {
_object = new SomeObject();
}
}
}
return _object;
}
}
}
What is your opinion? Do you see anything wrong (btw, suppose SomeObject is a reference type with some properties). I’ll return tomorrow and we’ll come back to this discussion. Keep tuned!