有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java易失性会影响非易失性变量吗?

好吧,假设我有一堆变量,其中一个声明为volatile:

int a;
int b;
int c;
volatile int v;

如果一个线程写入所有四个变量(最后写入v),另一个线程读取所有四个变量(首先读取v),那么第二个线程是否看到第一个线程写入abc的值,即使它们本身没有声明为volatile?或者它可能看到陈旧的价值观吗

因为似乎有一些困惑:我不是故意做不安全的事。我只想了解Java内存模型和volatile关键字的语义。纯粹的好奇心


共 (1) 个答案

  1. # 1 楼答案

    我要谈谈我认为你们可能真正在探索的东西——搭载同步

    它看起来像是你试图使用的一种技术,包括使用一个易失性变量作为同步保护,与一个或多个其他非易失性变量配合使用。当下列条件成立时,此技术适用:

    • 只有一个线程将写入要保护的值集
    • 线程读取只有当易失性保护值满足某些条件时,该组值才会读取它们

    对于你的例子,你没有提到第二个条件成立,但我们还是可以检查它。writer的模型如下:

    • 写入所有非易失性变量,假设没有其他线程尝试读取它们
    • 完成后,向volatile guard变量写入一个值,表明满足了读卡器的条件

    读卡器的操作如下:

    • 随时读取volatile guard变量,如果其值符合标准,则
    • 读取其他非易失性变量

    如果volatile guard变量尚未指示正确的值,则读卡器不得读取其他非volatile变量

    guard变量充当一个门。它将关闭,直到编写器将其设置为特定值,或所有值都满足指示闸门现在打开的条件。非易失性变量被保护在门后。在大门打开之前,读者是不允许阅读的。一旦闸门打开,读者将看到一组非易失性变量的一致视图

    请注意,重复运行此协议是不安全的。一旦打开闸门,编写器就不能继续更改非易失性变量。此时,多个读卡器线程可能正在读取这些其他变量,它们可以查看这些变量的更新。看到一些但不是所有的更新会产生不一致的场景视图

    备份时,这里的诀窍是控制对一组变量的访问,而无需

    • 创建一个结构来保存它们,一个原子引用可以被交换,原子的,或者
    • 使用锁使写入和读取整个变量集的活动相互排斥

    在易变的guard变量上搭载是一种聪明的特技,而不是随便做的特技。对程序的后续更新可以打破上述脆弱条件,消除Java内存模型提供的一致性保证。如果您选择使用这种技术,请在代码中清楚地记录其不变量和需求