Why mutation causes races
A data race needs a write. If a value is immutable, never changing after it is built, then every access is a read and no race is possible no matter how many threads share it.
How immutability simplifies code
Sharing immutable data lets you skip locks on reads entirely:
- many threads can read the same object freely
- there is no torn read because nothing updates it
- to change state you create a new value instead of mutating the old one
This trades extra allocation for the removal of an entire class of bugs.
The handoff still needs care
Immutability protects the data, but publishing a new immutable value to other threads still needs a synchronization point so they see the fully constructed object.
Key idea
Immutable data removes the write that a race needs, so shared reads need no locks, though publishing a new value still requires a synchronization point.