我在Java中使用volatile关键字,并且我有这段代码试图显示一个线程不会看到另一个线程引入的更改,除非我们将数据声明为volatile。我期望下面的代码永远不会终止,因为我还没有将共享数据声明为volatile。为什么此代码实际上会终止的任何想法?
public class VolatileTest {
public static void main(String[] args) throws InterruptedException {
var holder = new Holder();
new Thread(() -> {
try {
Thread.sleep(500);
} catch (InterruptedException e) { }
for(int i = 0; i<100000; i++) {
holder.counter++;
}
}).start();
var t = new Thread(() -> {
while(holder.counter < 10000) {
System.out.println("Jestem w pętli");
try {
Thread.sleep(400);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
t.start();
t.join();
}
static class Holder {
int counter = 0;
}
}
Thread 1
如果不使用Thread 2
,可能不会立即看到volatile
的更改,但是最终将来一次,当Thread 2
清空CPU高速缓存到主内存时会发生这种情况。在您的示例中,如果在volatile
字段上使用counter
,则在您调用holder.counter++
时,写入线程将始终写入主内存,而在您每次调用holder.counter < 10000
时,读取线程将从主内存中读取。