I'm trying to understand what thread interference is. This is an explanation about thread interference from Java official site.
Thread A: Retrieve c.
Thread B: Retrieve c.
Thread A: Increment retrieved value; result is 1.
Thread B: Decrement retrieved value; result is -1.
Thread A: Store result in c; c is now 1.
Thread B: Store result in c; c is now -1.
so I added codes to see c's changes.
In the picture(4th line), Shouldn't 1th decrement:(Retrieve C) 0 be -1? why it's 0?
Also, if you see this below result, 2th decrement:(Retrieve C) is -1.
I think 2th decrement(Decreased C) should be -2, but it's still -1.
I don't understand. Can someone explain my reslt?
2th decrement:(Retrieve C) -1
2th decrement(Decreased C) -1
public class Counter {
private int c = 0;
public void increment(){
for(int i=0; i<1000; i ){
System.out.println(i "th increment:(Retrieve C) " c);
c ;
System.out.println(i "th increment:(Increased C) " c);
}
}
public void decrement(){
for(int i=0; i<1000; i ){
System.out.println(i "th decrement:(Retrieve C) " c);
c--;
System.out.println(i "th decrement(Decreased C) " c);
}
}
public int getC(){
return c;
}
public static void main(String[] args) throws InterruptedException{
Counter c = new Counter();
Thread t1 = new Thread(() -> {
c.increment();
});
Thread t2 = new Thread(() -> {
c.decrement();
});
t1.start();
t2.start();
t1.join();
t2.join();
}
}
CodePudding user response:
The line c ;
actually does three things, one after the other.
- It reads the value of
c
. - It increments what it saw.
- It saves the new value back into
c
.
The operations is not atomic, which means there's no guarantee that c
won't change independently while it's doing that. Likewise for c--;
.
So while you've got two threads doing similar things to the same variable c
, it's very likely that one of them is going to change c
while the other is doing its work. And that seems to be what you're seeing.
In fact, by printing c
in both threads, you're increasing the likelihood that one of the threads will change the value of c
between the times when the other thread prints its two messages.
CodePudding user response:
The term 'interference' has no official meaning. Your code is suffering from 2 problems
race condition: because the read and write aren't atomic, and therefore you can run into lost updates.
data race: because the access to the 'c' variable isn't synchronized, there is no happens-before edge. To gain a deeper understanding, you need to dig into the Java Memory Model.
Both problems can easily be solved by making 'c' an AtomicInteger and use the increment/decrement methods.