public class DataRace {
static int a = 0;
public static void main() {
new MyThread().start();
a = 1;
}
public static class MyThread extends Thread {
public void run() {
System.out.println(a);
}
}
}
以上两个线程间就存在简单数据竞争
The second thread could be scheduled immediately, printing the initial value of 0 for a
. Alternately, the second thread might not run immediately, resulting in the value 1 being printed instead. The output of this program may depend on the JDK you are using, the scheduler of the underlying operating system, or random timing artifacts. Running it multiple times could produce different results.
There is actually another data race in Listing 1, besides the obvious race of whether the second thread starts executing before or after the first thread sets a
to 1. The second race is a visibility race: the two threads are not using synchronization, which would ensure visibility of data changes across threads. Because there's no synchronization, if the second thread runs after the assignment to a
is completed by the first thread, changes made by the first thread may or may not be immediately visible to the second thread. It is possible that the second thread might still see a
as having a value of 0 even though the first thread already assigned it a value of 1. This second class of data race, where two threads are accessing the same variable in the absence of proper synchronization, is a complicated subject, but fortunately you can avoid this class of data race by using synchronization whenever you are reading a variable that might have been last written by another thread, or writing a variable that might next be read by another thread. We won't be exploring this type of data race further here, but see the "Synching up with the Java Memory Model" sidebar and the Resources section for more information on this complicated issue.
Synching up with the Java Memory Model