Thread Safety in Java
To Get a better understanding of this topic read the below two post before continuing this post.
What Is Multi Threading ? Why Do We Need Multi Threading In Java - Explained [THEORETICAL]
How To Achieve Multi Threading in Java ? Extending Thread Class | Implementing Runnable Interface
Multi Threading Using Lamda Expression | Join and IsAlive Methods In Multi Threading In Java
Priority In Java Multithreading | How To Name a Thread in Java
What is Mutable Objects ?
If we are able to change the value of an object(i.e., the value of the variable the object is holding) then the object is called as Mutable Object. And the process of changing it is called as Mutation.
Similarly If we cannot change the value of an object then it is called as Immutability.
Since we will need to change the values of the objects in real world scenarios , i.e., Mutation is important.
The problem comes when we have multithreading and when we are trying to change the value of the objects.
In Multithreading when we changing the value the conflict occurs . Let's understand it with the help of below code.
The below code has made used of multithreading. it has 2 threads each thread is given a task of incrementing 1000 times. so we should get 2000 as the output.
code:
class Counter
{
int count;
public void increment()
{
count++;
}
}
class ExampleCode
{
public static void main(String[] args) throws Exception
{
Counter c = new Counter();
Thread t1 = new Thread(new Runnable()
{
public void run()
{
for(int i=1;i<=1000;i++)
{
c.increment();
}
}
});
Thread t2 = new Thread(new Runnable()
{
public void run()
{
for(int i=1;i<=1000;i++)
{
c.increment();
}
}
});
t1.start();
t2.start();
t1.join();
t2.join();
System.out.println(c.count);
}
}
Output:
If we run the code we will be expecting 2000 but we will get different output when we run each time. below are some of the outputs.
We can note that one time we got 2000 among 4 times running. why is this inconsistency occurs?
we should get 2000 all the time but we are not getting it . why ?
The answer is that we have a shared data i.e., the count variable is being accessed by two threads.
So the only way to resolve this problem is to make the shared data to be access by only one thread at a time.
when one thread is accessing other thread should not been allowed to access the data
There are many ways to achieve this.
Way 1 : Using synchronization keyword.
code:
class Counter
{
int count;
public synchronized void increment()
{
count++;
}
}
class ExampleCode
{
public static void main(String[] args) throws Exception
{
Counter c = new Counter();
Thread t1 = new Thread(new Runnable()
{
public void run()
{
for(int i=1;i<=1000;i++)
{
c.increment();
}
}
});
Thread t2 = new Thread(new Runnable()
{
public void run()
{
for(int i=1;i<=1000;i++)
{
c.increment();
}
}
});
t1.start();
t2.start();
t1.join();
t2.join();
System.out.println(c.count);
}
}
By making the increment method as synchronized it will allow one thread only to access the method at a time.
Way 2: Making use of Atomic Wrapper Class
code :
import java.util.concurrent.atomic.AtomicInteger;
class Counter
{
AtomicInteger count =new AtomicInteger();
public synchronized void increment()
{
count.incrementAndGet();
}
}
class ExampleCode
{
public static void main(String[] args) throws Exception
{
Counter c = new Counter();
Thread t1 = new Thread(new Runnable()
{
public void run()
{
for(int i=1;i<=1000;i++)
{
c.increment();
}
}
});
Thread t2 = new Thread(new Runnable()
{
public void run()
{
for(int i=1;i<=1000;i++)
{
c.increment();
}
}
});
t1.start();
t2.start();
t1.join();
t2.join();
System.out.println(c.count);
}
}
Inspite of using int we are using AtomicInteger to make it thread safe.
we have a method of incrementAndGet() with the Atomic Integer which does the job of maintaining thread safety.
Nice Post!!
ReplyDeletePlease Look Here At Coding Classes