Synchronization
Whenever you need to access the same data from multiple threads, and at least one thread is modifying the data, you have to synchronize access to the data. As we’ve just seen, this holds for shared data structures and for simple variables.
Synchronization will make sure that one thread cannot see invalid intermediate states that another thread creates temporarily while updating the shared data. In a way, this is similar to database transactions at the read committed level, when other users cannot see changes applied to the database while a transaction is in progress.
The simplest way to synchronize two (or more) threads is to use locking. With locking, you can protect a part of the program so that only one thread will be able to access it at any time. If one thread has successfully acquired but not yet released the lock (we also say that the thread now owns the lock), no other threads will be able to acquire that same lock. If any thread tries to acquire...