i have two Threads that increment a shared variable x
of an object myObject
.
And when incrementing this number a 1000 times for each thread, i don't get 2000, i only get less.
And i know this is bad and shouldn't be done, but am just trying to figure out where is the "problem" happening in the code.
Is it because in run
method myObject.x = myObject.x 1
is entrepeted like this :
int temp = myOject.x
temp = temp 1; //The compiler/something pauses here and goes to thread 2
myObject.x = temp; //Dind't actually get here so no incrementation ?
Or because the two threads tried to access myObject.x
at the same time, so it's like only it was incremented only ones ?
the threads look like this :
public class Ex4Incr extends Thread{
private MyObject myObject;
public Ex4Incr(MyObject myObject ) {
this.myObject = myObject ;
}
@Override
public void run() {
for(int i = 0;i < 100;i ) {
myObject .setX(myObject.getX() 1);
}
System.out.println("id:" Thread.currentThread().getId() " x is: " myObject.getX());
}
}
Am sorry that i din't add code but this problem is well known but i just didn't know what expalanation is true.
CodePudding user response:
Has nothing to do with the compiler. The Thread Scheduler decides which threads to run and which to pause based on a scheduling algorithm. It may suspend one thread after the variable value, say 2
is already read into temp
and run the other thread instead. This thread now also reads the variable value 2
increments it to 3
and writes it back. If now the first thread continues to run it continues in the second line so temp = 2
, then increments to 3
and writes it back into memory. Now we've actually performed two updates but we've done the same update twice therefore one update "got lost" if you will.
An easy way to solve this is to make your int
an AtomicInteger
and use its method incrementAndGet()
.
There are however other possibilities like using a Monitor (synchronized
keyword), Lock etc. to solve the problem at hand (known as Race Condition).