public class App {
private int number = 0;
public static void main(String args[]){
App app = new App();
app.increment();
}
public void increment(){
Thread t1 = new Thread(new Runnable(){
@Override
public void run() {
for(int i=0;i<10000;i++){
number=number+1;
}
}
});
Thread t2 = new Thread(new Runnable(){
@Override
public void run() {
for(int i=0;i<10000;i++){
number=number+1;
}
}
});
t1.start();
t2.start();
try {
t1.join();
t2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Count is: "+ number);
}
}
In method increment()
it starts two threads, wait for them to stop and finally print the variable number
.After increment 10000 times by each thread value of variable number
should be 20000, because there are two threads involved in this process.
This code seems like work fine. But there is a problem. If you run it few times, you will see some times the value of variable
number
is lower than 20000.Why is that..?? What is happening there..??
There are situations in a multi-threading environment that two or more threads access or do operations on same variable at the same time.
Figure 1 : Two threads accessing same variable at the same time
Figure 1 shows a simple scenario, what happens when two threads access same variable at same time.
In the above scenario,
- Both threads reads the same value
- Both threads increment retrieved value by one
- Both threads write the value to variable
So the expected work from two threads have not been done.
This can be prevented if we can stop two threads accessing same variable at the same time. That when
synchronized
keyword of the java comes to help. with that above code can be modified as follows.
public class App {
private int number = 0;
public static void main(String args[]){
App app = new App();
app.increment();
}
public synchronized void incByOne(){
number=number+1;
}
public void increment(){
Thread t1 = new Thread(new Runnable(){
@Override
public void run() {
for(int i=0;i<10000;i++){
incByOne();
}
}
});
Thread t2 = new Thread(new Runnable(){
@Override
public void run() {
for(int i=0;i<10000;i++){
incByOne();
}
}
});
t1.start();
t2.start();
try {
t1.join();
t2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Count is: "+ number);
}
}
In this we have created method incByOne()
with synchronized
to increment the number by one and that will be called inside a thread.Method marked as synchronized can only be called by only one thread at a time.so the accessing same variable at the same time by two threads won't be happened.
This happens because every object in java has a intrinsic lock or a monitor lock also called a mutex. If a thread calls synchronized method of a object, (In this case synchronized method of App object) that thread has acquire the intrinsic lock of that object. If another thread want to call that synchronized method it has to wait until the first thread releases the intrinsic lock.
No comments:
Post a Comment