Types of Immutability


By definition, an immutable object in computer science is one that is not able to change.  Parallel coding is becoming more necessary as the number of cores in a processor are increasing but not the overall speed.  As such immutability is will become more important because it is an important asset of multithreaded programming.  Immutable objects are inherently thread safe. 

Like other categorizations in computer science, there are degrees of being unable to change.  This post is an attempt to outline and categorize several of the variations.

Note: these are not standard categorizations.  They are merely my attempt to name several of the scenarios you can encounter with immutable objects.

Immutable

Object itself has no fields that can change.  In addition all of it’s fields are also Immutable and thus cannot be changed.  This object is carved in stone and short of process corruption, it will be the same in every way.

For primitives excluding string this can be ensured by making them read only (.initonly in IL).  For reference types the field must be read only and the type must also meet the Immutable guidelines.

Types with meet the Immutable guarantee are inherently thread safe.  They are not subject to race conditions because they cannot be changed and thus viewed differently between threads. 

Shallow Immutable

The direct contents of this object must be immutable in the sense that they cannot be changed to point to another object.  However there is no guarantee that all of the fields are themselves immutable. 

All of the fields in the object must be read only.  For primitive values this is enough to guarantee them meeting the Immutable guidelines and hence Shallow Immutable.  For reference types this will ensure they will point to the same object thus doing all that is needed to meet the Shallow Immutable Guarantee. 

Types with this guarantee are thread safe to a degree.  They are thread safe as long as you are accessing the fields with meet the Immutable guarantee.  You can also access the references which are read only as long as you do not call any instance methods.  For instance a Null check is thread safe. 

Shallow Safe Immutable

Slightly stronger guarantee than Shallow Immutable.  For all fields that are read only but not immutable, the type must be thread safe. 

Types which meet this guarantee are thread safe also to a degree.  They are as thread safe as the fields which are guaranteed to be thread safe. 

Comments (3)

  1. johnnylightbulb says:

    One race condition to watch out for is a process reading an immutable structure while another process writes over the same structure – When those two things collide over different threads you will wind up with your readonly struct containg some values from the previous struct and some from the new struct.

    Use lock(obj) on some syncrhonizing object to prevent this.

  2. That’s what is great about immutable objects though.  This can’t happen.  An immutable object is not subject to change therefore there is no race condition because no routine can modify the object once it’s created.  

  3. johnnylightbulb says:

    Maybe this example is overkill, butL the other day I built a small app (Thanks Express versions!) to test out what will be part of a larger codebase. It was pretty simple:

    – A struct with multiple readonly int’s

    – A writer thread that constantly writes new stucts to a class variable, always making all int’s on the struct the same (random value)

    – A reader thread that constantly reads the class variable struct

    I just set it to throw an exception whenever the reader found a struct which has different values in it’s ints (a mutant of two structs that shouldn’t be). I guess I vainly hoped .NET would take care of that for me, and I guess they did with the lock statement… Oh well..

    It would be neat if Interlocked had a method for this that didn’t require boxing..