Last Updated : 11 Jul, 2025
Javaallows
multithreadingwhich involves concurrent execution of two or more parts of the program. It enhances CPU utilization by performing multiple tasks simultaneously. The
threadscommunicate with each other by sharing object references and member variables.
When Two threads access the same shared memoryThis communication in multithreading can cause two types of errors, if not implemented properly:
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:
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
// Java program to explain the
// concept of thread interference.
import java.io.*;
// Creating thread by creating the
// objects of that class
class 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:
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:
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4