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

fre*_*low 10 java multithreading volatile

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

int a;
int b;
int c;
volatile int v;
Run Code Online (Sandbox Code Playgroud)

如果一个线程写入所有四个变量(写入v最后一个),另一个线程从所有四个变量读取(从v第一个读取),那么第二个线程是否会看到写入的值a,b并且c由第一个线程,即使它们本身不是声明挥发?或者它可能会看到过时的价值观?

由于似乎存在一些混乱:我并不刻意尝试做一些不安全的事情.我只想了解Java内存模型和volatile关键字的语义.纯粹的好奇心.

seh*_*seh 12

我将谈谈我认为你可能正在探究的事情 - 捎带同步.

它的技术看起来像你正在尝试使用包括使用一个volatile变量作为演唱会同步后卫与一个或多个其他非易失性变量.当满足以下条件时,此技术适用:

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

你没有提到你的例子中第二个条件为true,但无论如何我们都可以检查它.对于该模型的作家如下:

  • 写入所有非易失性变量,假设没有其他线程会尝试读取它们.
  • 完成后,将值写入易失性保护变量,以指示满足读者的标准.

阅读器操作如下:

  • 随时读取易失性保护变量,如果其值符合标准,则
  • 阅读其他非易失性变量.

如果易失性保护变量尚未指示正确的值,则读者不得读取其他非易失性变量.

保护变量充当门.它一直关闭,直到作者将其设置为特定值或一组值,这些值都满足指示门现在打开的标准.非易失性变量在门后守卫.在门打开之前,不允许读者阅读它们.一旦门打开,读者将看到一组非易失性变量的一致视图.

请注意,这是不是安全的反复运行这个协议.一旦打开门,编写者就无法继续更改非易失性变量.此时,多个读取器线程可能正在读取其他变量,并且它们可能 - 虽然不能保证 - 看到这些变量的更新.查看一些但不是所有这些更新将产生该集合的不一致视图.

备份,这里的技巧是在没有任何变量的情况下控制对一组变量的访问

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

在易变的防守变量之上捎带是一个聪明的特技 - 不是随便做的.对程序的后续更新可以打破上述脆弱条件,从而消除Java内存模型提供的一致性保证.如果您选择使用此技术,请清楚地记录代码中的不变量和要求.

  • 谢谢,最好的.如您所描述的那样使用计数器解决了*ABA*问题,如果您使用布尔标志来指示编写器是否处于活动状态(如"AtomicStampedReference"),则会出现该问题.尽管如此,我认为你需要某种"无效"的值,它允许读者区分编写者*开始*更新非易失性变量的情况,但还没有改变版本号.也许*一对变量就足够了:第一个作为交易号,第二个作为提交号.颠簸第一个,通过碰撞第二个提交. (2认同)

Tom*_*ine 6

是.volatile,锁等,设置发生在之前的关系,但它影响所有变量(在Java SE 5/JDK 1.4的新Java内存模型(JMM)中).有点使它对非原始挥发物有用......