When you use mutable types you are exposing yourself to Write-After-Read or Write-After-Write errors. These are synchronisation errors associated with updating a value while other threads are concurrently reading or updating the value.
To prevent synchronization errors you must use some form of locking mechanism. If you do use explicit locking you will need to be very careful about the order of acquiring locks. If you are not careful you can introduce deadlocks. For example: Thread A acquires Lock X, then Thread B acquires Lock Y. A while later Thread A requests Lock Y and Thread B requests Lock X. This causes both threads to wait indefinitely for Locks that will never be released.
Two good rules of thumb for locking:
- Acquire locks in a specific order (e.g. always acquire Lock X before Lock Y)
- Hold locks for as short a time as possible. Acquire them when you need them, and release them as soon as you're done with the.
If you never write to an object after its creation, you do not need to lock it before accessing it. Thus, you will not need to lock immutable objects.