【发布时间】:2021-11-11 01:17:45
【问题描述】:
我已经阅读了java中volatile的定义,我运行了一个如下的小测试项目:
public class MainActivity extends AppCompatActivity
{
static int num = 0;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Thread readerThread = new Thread(() -> {
int temp = 0;
while (true)
{
if (temp != num) {
temp = num;
System.out.println("reader: value of num = " + num);
}
}
});
Thread writerThread = new Thread(() -> {
for (int i = 0; i < 5; i++) {
num++;
System.out.println("writer: changed value to = " + num);
//sleep for readerThread to have enough time to read the change of num, since num++ is not atomic
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.exit(0);
});
readerThread.start();
writerThread.start();
}
}
如果我在 Eclipse 上运行主代码,我会得到如下日志:
writer: changed value to = 1
reader: value of num = 1
writer: changed value to = 2
writer: changed value to = 3
writer: changed value to = 4
writer: changed value to = 5
也就是说,我猜是对的,结果意味着读取器没有从主存中获取值,而是从缓存中获取。
但是,如果我通过 android studio 在真实的 android 设备上构建代码,我得到的日志是:
I/System.out: reader: value of num = 1
I/System.out: writer: changed value to = 1
I/System.out: reader: value of num = 2
I/System.out: writer: changed value to = 2
I/System.out: writer: changed value to = 3
I/System.out: reader: value of num = 3
I/System.out: writer: changed value to = 4
I/System.out: reader: value of num = 4
I/System.out: writer: changed value to = 5
I/System.out: reader: value of num = 5
似乎没有 volatile 读者仍然可以从主存中获取值,为什么这两者之间的结果不同?
【问题讨论】:
-
所以...如果您不使用 volatile,则未指定读者是否会看到作者所做的更改。而且您在不同的平台上运行代码,在这种 unspecified 案例中发生的事情是不同的。当您的应用程序执行超出 Java 指定行为的事情时,就会发生这种情况。
-
而不是找出“测试”,而是找出规范并确保您的代码能够正常工作。这里有很多的问题,特别是最大的一个是
num++,你认为它是原子的,而原子性与volatile无关。 -
我的意思是
volatile是关于 happens-before 边缘,而不是“主内存”。volatile保证在规范中。其他一切都很好,未指定(船长很明显,我知道)。当某些事情未指定时 - 您处于危险之中,无论是现在,十年后,在 Android 上还是在 M1 上。 -
顺便说一句,您的问题以“我已经阅读了 java 中 volatile 的定义...”开始,但后来您使用“主内存”之类的词并使用
num++等。我想你最初的灵感来源并不好。有很多关于这个的好文章,但我会给你this link(我的,是的)应该让你开始 -
是的。在存在“数据竞赛”的地方,可能会发生很多丑陋的事情。
标签: java android multithreading eclipse volatile