Imagine two tasks sharing one printer: without controlled access, their actions can conflict and leave the application—or the whole system—in an unknown state. Thread safety means a function or operation still behaves correctly when multiple tasks access it, whatever scheduling or interleaving occurs. section 8.1
The safest design usually shares as little as possible and minimizes communication between tasks. When sharing cannot be avoided, synchronized access must prevent operations from alternating in ways that produce incorrect results. section 8.1 section 8.2
Practical safeguards include:
- Prefer immutable objects and pure functions when they fit; unchanged state cannot be corrupted by thread interference or observed inconsistently. section 8.1
- Check whether libraries are thread safe before concurrent use; synchronize their calls or abandon libraries whose global state cannot support concurrent access. section 8.2
- Consider message-passing IPC instead of shared memory so tasks work with their own data copies. section 9.10
A bank account race
Suppose many ATM tasks each deposit 10 and then withdraw 10. An unsynchronized account can finish with a balance of 380 instead of the expected 0 because concurrent reads and writes interfere. Timing changes, such as inserting sleeps, may help expose the problem, but synchronization is needed to prevent the incorrect interleaving. section 8.2
Synchronization improves correctness but costs performance: locks introduce delays, require processor and synchronization work, and can limit scalability when many tasks contend for one lock. section 9.10







