Thread-safe code is code that remains correct when executed by multiple threads. Thus, No sequence of operations can violate the specification.
1 Invariants and conditions will hold during multithread execution without requiring additional synchronization by the client
2. The high level takeaway point is: thread-safe requires that the specification holds true during multithread execution. To actually code this, we have to do just one thing: regulate the access to mutable shared state
3. And there are three ways to do it: Prevent the access. Make the state immutable. Synchronize the access.
The first two are simple. The third one requires preventing the following thread-safety problems:
liveness deadlock: two threads block permanently waiting for each other to release a needed resource.
livelock: a thread is busy working but it’s unable to make any progress.
starvation: a thread is perpetually denied access to resources it needs in order to make progress.
safe publication: both the reference and the state of the published object must be made visible to other threads at the same time.
race conditions: A race condition is a defect where the output is dependent on the timing of uncontrollable events. In other words, a race condition happens when getting the right answer relies on lucky timing. Any compound operation can suffer a race condition, example: “check-then-act”, “put-if-absent”. An example problem would be if (counter) counter — ;, and one of several solutions would be
@synchronize(self)
{
if (counter) counter — ;
}.