In Java threading support, threads mostly communicate with each other via shared objects or shared member variables within the same object. Three type of complications can arise from this when multiple threads are allowed to access the same piece of memory.
- Thread Interference. Different threads access (read and write) the same data. This can lead to race conditions. The program behavior (what gets stored in the shared memory) depends on the order in which threads get access. This can cause non-deterministic behavior.
- Memory Consistency Errors. If multiple threads are updating the same variable, they can see a stale (inconsistent) value of a variable.
- Thread Contention. If locks are not used correctly, threads can get in each other's way, and slow down or sometimes even have to be killed by Java.
Let's look at the first two problems. If two threads access the same variable, it is possible for them to get in each other's way. That is because Java might switch execution from one thread to another even midway through a simple, seemingly atomic instruction. For example, two threads incrementing the same variable could simply 'loose' one of the two increments.
The solution is to make sure that a section of code that should be atomic is accessed by one thread at a time. Restricting access to an object or a variable - akin to locking the variable so that only one thread can access at a time - is widely used, e.g., in databases.
Locking variables correctly can eliminate the first two problems - Thread Interference and Memory Consistency Errors, but it slows down performance, and can lead to the third problem - Thread Contention issues, namely, Starvation, Livelock, Deadlock, to name a few. This essentially means that a particular thread can no longer make progress.
The Synchronized Keyword
- The "only-one-thread-at-a-time" restriction applies to the same method of the same object
- If the method does something to a static class variable, errors can still result
Thread Contention
- Deadlock. Two threads, each is blocked on a lock held by the other. For example, if there are two threads - T1 and T2 and two locks - L1 and L2. If T1 holds L1 and T2 holds L2 and T1 needs L2 and/or T2 needs L1 to proceed, they are in a deadlock condition, i.e., they are stalled completely.
- Livelock. Two threads keep blocking on locks held by the each other repeatedly.
- Starvation. Some threads keep acquiring locks greedily, and cause other threads to be unable to get anything done.
Comments
Post a Comment