Thread Interference and Memory Consistency Errors in Java - GeeksforGeeks

29 Mar, 2019
Java allows multithreading which involves concurrent execution of two or more parts of the program. It enhances CPU utilization by performing multiple tasks simultaneously. The threads communicate with each other by sharing object references and member variables.When Two threads access the same shared memory
This communication in multithreading can cause two types of errors, if not implemented properly:
Thread interferenceMemory inconsistency
Thread interference
Memory inconsistency
When multiple threads share the same memory, there is a chance that two or more different threads performing different operations on the same data interleave with each other and create inconsistent data in the memory. Threads interleave when they are performing operations with multiple steps and their sequence of steps overlap. This is called thread interference.
Even for a small operation like incrementing or decrementing the value of a variable (say i) using the statement i++ or i–, the virtual machine performs multiple steps as follows:
Retrieve the value of i from the memoryIncrement/Decrement the value of i by 1Store the new incremented/decremented value of i back to the memory
Retrieve the value of i from the memory
Increment/Decrement the value of i by 1
Store the new incremented/decremented value of i back to the memory
If there are two threads A and B operating on the same object, A performs the increment operation and B performs decrement operation at the same time, it might lead to data inconsistency. If the initial value of i is 10. Thread A reads the value of i from the memory as 10 and increments its value to 11. Before it could store the new value to the memory, thread B reads the value of i from the memory as 10, since the memory has not been updated yet. Now, thread B decrements the value of i to 9. The new value in the memory now would be either 9 or 11, where the expected value was actually 10. Either one of the thread’s result may be lost and overwritten by the other or there could be no error at all. Being unpredictable, thread interference bugs are difficult to detect and fix.
Sequence diagram for thread interference error
Example:
// Java program to explain the// concept of thread interference.import java.io.*;  // Creating thread by creating the// objects of that classclass SharedClass {    static int i=10;    void increment()    {        for(int j=0;j<50;j++)        {                // incrementing value of i             i=i+1;            System.out.println("i after increment "+i);        }    }    void decrement()    {        for(int j=0;j<50;j++)        {                // decrementing value of i             i=i-1;            System.out.println("i after decrement "+i);        }    }}  class GFG {    public static void main(String[] args)    {        final SharedClass s1 = new SharedClass();        Thread t1 = new Thread()        {            @Override            public void run()            {                s1.increment();            }        };        Thread t2 = new Thread()        {            @Override            public void run()            {                s1.decrement();            }        };        t1.start();        t2.start();    }}
In the above code the last line of the expected output should be either “i after increment 10” or “i after decrement 10”, but the actual output may vary due to the interference of the threads. Thread interference is unpredictable, try running the above code several times to find the thread interference error in some cases. The interleaving thread operations would be evidently seen.
How to avoid thread interference errorThread interference can be avoided by making the code thread-safe through:
Synchronization
Access restriction on the same object by multiple threads
Declaring the variable as final.
Declaring the variable as volatile.
Creating immutable objects.
In multithreading, there can be possibilities that the changes made by one thread might not be visible to the other threads and they all have inconsistent views of the same shared data. This is known as memory consistency error.
Memory consistency is more of an architecture-based concept than Java-based. Accesses to main memory might not occur in the same order in which the CPU initiated them, especially for write operations which often go through hardware write buffers so that the CPU need not wait for them. CPUs guarantee that the order of writes to a single memory location is maintained from the perspective of all CPUs, even if CPUs perceive the write time of other CPUs differently than the actual time. This sometimes leads to memory inconsistency due to lack of visibility of the correct data.
Sequence diagram for memory consistency error
How to avoid memory consistency errorsMemory consistency errors can be avoided by establishing a happens-before relationship. This relationship guarantees that memory writes operation performed by one thread is visible to a read operation by any other thread on the same shared memory.
The following actions can create a happens-before relationship:
Thread.start() – This statement makes the effects of code that led up to the creation of the new thread visible to the new thread.
Thread.join() – This statement makes the effects of the code in the thread visible to the thread that performed the join.
Prashasti Baranwal
java-basics
Java-Multithreading
Java
Java
Writing code in comment?
Please use ide.geeksforgeeks.org,
generate link and share the link here.
Comments
Old Comments
Functional Interfaces in Java
Stream In Java
Constructors in Java
Different ways of Reading a text file in Java
Exceptions in Java
Generics in Java
Comparator Interface in Java with Examples
Strings in Java
How to remove an element from ArrayList in Java?
Difference between Abstract Class and Interface in Java