Reputation: 51
This is my code that sum variable 'res' by one 4*10^7 time using 4 threads:
class MathSin extends Thread {
public double a;
public MathSin(int degree) {
a = degree;
}
@Override
public void run() {
for (int i = 0; i < Math.pow(10., 7); i++)
MathThreads.res++;
}
}
class MathThreads {
public static double res = 0;
public static void main(String args[]) {
MathSin st = new MathSin(8);
MathSin ct = new MathSin(8);
MathSin tt = new MathSin(8);
MathSin qt = new MathSin(8);
st.start();
ct.start();
tt.start();
qt.start();
try { // wait for completion of all thread and then sum
st.join();
ct.join(); // wait for completion of MathCos object
tt.join();
qt.join();
System.out.println(res);
} catch (InterruptedException IntExp) {
}
}
}
and these are some of answers :
1.8499044E7
2.3446789E7
.
.
.
I expected get 3.0E7 but get another different answers.
how can fix this problem?
Upvotes: 0
Views: 100
Reputation: 53819
You are observing race conditions while updating the static
variable res
.
MathThreads.res++
is equivalent to:
double tmp = MathThreads.res;
MathThreads.res = tmp + 1;
Now what happened if two threads reads at the same time a value for tmp
, and both update res
with tmp + 1
? Well, one increment has simply been forgotten: res
ends being tmp + 1
instead of being tmp + 1 + 1
!
So with 4 threads updating res
concurrently, you simply end up with an undefined behavior : it is impossible to predict the final value of res
because of those race conditions. Two executions of the same code will give you different answers.
To make your code thread-safe, you need to use a thread-safe structure for res
: a structure that can be concurrently updated and accessed.
In your case, an AtomicLong
seems the perfect choice:
public static AtomicLong res = new AtomicLong(0);
And in the run method:
for (int i = 0; i < Math.pow(10., 7); i++) {
MathThreads.res.incrementAndGet();
}
Upvotes: 5