Synchronization is not only protecting critical sections. It also provide memory visibility. That means, when one thread modify the state other threads should be able to see the changes without any issue.
We should not share objects without proper synchronization. Unless it will lead to stale data which causes;
- Unexpected exceptions.
- Infinite loops.
- Corrupted data.
- Inaccurate results.
Out of thin air safety
A thread can see some value of shared data which is updated by another thread (even it is stale) is called out-of-thin-air safety.
All threads should see most up-to-date values of shared mutable variables.
It is a weaker form of synchronization.
- Do not re-order.
- Put in shared memory (not in cpu's cache).
- Good for simple situations like maintaining a flag, completion flag.
- Does not guarantee atomicity. Guarantee only visibility.
Make an object available outside of its current scope.
- public variables.
- non private setters.
Publish an object when it should not.
When data is not shared and accessible only form single thread it is called thread confinement.
Non-safe objects within the thread context is still thread-safe.