问题
Here the code
class Aux implements Runnable {
private Boolean isOn = false;
private String statusMessage;
private final Object lock;
public Aux(String message, Object lock) {
this.lock = lock;
this.statusMessage = message;
}
@Override
public void run() {
for (;;) {
synchronized (lock) {
if (isOn && "left".equals(this.statusMessage)) {
isOn = false;
System.out.println(statusMessage);
} else if (!isOn && "right".equals(this.statusMessage)) {
isOn = true;
System.out.println(statusMessage);
}
if ("left".equals(this.statusMessage)) {
System.out.println("left " + isOn);
}
}
}
}
}
public class Question {
public static void main(String [] args) {
Object lock = new Object();
new Thread(new Aux("left", lock)).start();
new Thread(new Aux("right", lock)).start();
}
}
In this code I expect to see:
left, right, left right and so on,
but when Thread with "left" message changes isOn to false, Thread with "right" message don't see it and I get ("right true" and "left false" console messages), left thread don't get isOn in true, but right Thread can't change it cause it always see old isOn value (true).
When i add volatile modifier to isOn nothing changes, but if I change isOn to some class with boolean field and change this field then threads are see changes and it works fine
Thanks in advance.
回答1:
isOn
is a thread local variable, so when one thread modifies it, the other thread won't see the changes. When you use a class with a boolean field, you're presumably giving each thread the same instance of the class, meaning that the threads will see changes made by the other threads. However, you create two instances of Aux
instead of using just one.
If you want it to work on two different instances, try adding the static
modifier (along with the volatile
modifier) to the Boolean
field; otherwise, don't create a second Aux
.
来源:https://stackoverflow.com/questions/17385211/java-threads-dont-see-shared-boolean-changes