关于volatile关键字的“Java Threads”一书的引用

时间:2011-05-30 11:32:39

标签: java volatile

我只是想知道是否有人可以解释这个的含义:

  

增量和增量等操作   减量(例如++--)不能   用于volatile变量因为   这些操作都是语法糖   负载,变更和商店。

我认为增量和减量应该适用于一个易变量的变量,唯一的区别是每次你读或写时你都要从主内存访问/写入而不是从缓存中访问。

5 个答案:

答案 0 :(得分:8)

volatile变量确保visibility。它不能确保atomicity。我猜,这就是解释声明的方式。

答案 1 :(得分:7)

我认为你的报价是脱离背景的。

当然++-- 可以应用于volatile变量。它们不会是原子的。

由于volatile 经常意味着必须以原子方式处理它们,这与目标背道而驰。

++--的问题在于,他们可能感觉就像他们是原子的一样,而实际上他们不是。

执行a = a + 1使它(某种程度上)明确表明它不是原子操作,但是一个可能(错误地)认为a++是原子的。

答案 2 :(得分:3)

Java语言规范没有++--运算符的原子操作。换句话说,当您以下列方式编写代码时:

a++;

Java编译器实际上发出的代码类似于下面的一组步骤(实际指令将根据变量的性质而变化):

  1. 使用load数据的操作之一将操作数加载到堆栈中。
  2. 复制堆栈上操作数的值(以便稍后返回)。这通常使用dup操作完成。
  3. 增加堆栈上的值。通常使用VM中的iadd操作完成。
  4. 返回值(在步骤2中获得)。
  5. 正如您所看到的,VM中有多个操作通常被认为是原子操作。 VM可以确保原子性仅达到单个操作的级别。任何进一步的要求只能通过同步或其他技术来实现。

    使用volatile关键字,允许其他线程获取变量的最新值;对变量的所有读取操作都将基于每个指令返回最近更新的值。例如,如果变量a在前面的示例中是易变的,那么读取a值的线程如果在指令2之后读取a则会看到不同的值。在指示之后3.使用volatile并不能防止这种情况发生。它可以防止多个线程在指令2(例如)之后看到a的多个值的情况。

答案 3 :(得分:1)

挥发性不会在涉及多个步骤的操作中保证原子性。

以这种方式看待它我正在读取一个值而且这一切正在进行中,读取操作是一个原子操作。这是一个步骤,因此在这里使用挥发性就好了。但是,如果我正在读取该值并在写回之前更改该值,那么这是一个多步操作,并且对于此volatile不会管理原子性。

增量和减量操作是多步的,因此使用挥发性修饰剂是不够的。

答案 4 :(得分:0)

不 - 您使用“volatile”表示该变量可以由外部实体更改。 这通常是一些JNI C代码,或者是与某些硬件(如温度计)相关联的特殊寄存器。 Java无法保证所有体系结构上的所有JVM都能够在单个机器周期中递增这些值。所以它不会让你在任何地方做到这一点。