使用 volatile long 有什么意义吗? [英] Is there any point in using a volatile long?

查看:37
本文介绍了使用 volatile long 有什么意义吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我偶尔会使用 volatile 实例变量,以防我有两个线程读取/写入它,并且不想要取出锁的开销(或潜在的死锁风险);例如,一个计时器线程会定期更新一个 int ID,该 ID 作为某个类的 getter 公开:

I occasionally use a volatile instance variable in cases where I have two threads reading from / writing to it and don't want the overhead (or potential deadlock risk) of taking out a lock; for example a timer thread periodically updating an int ID that is exposed as a getter on some class:

public class MyClass {
  private volatile int id;

  public MyClass() {
    ScheduledExecutorService execService = Executors.newScheduledThreadPool(1);
    execService.scheduleAtFixedRate(new Runnable() {
      public void run() {
        ++id;
      }
    }, 0L, 30L, TimeUnit.SECONDS);
  }

  public int getId() {
    return id;
  }
}

我的问题:鉴于 JLS 仅保证 32 位读取将是原子的,使用 volatile long 是否有任何意义曾经?(即 64 位).

My question: Given that the JLS only guarantees that 32-bit reads will be atomic is there any point in ever using a volatile long? (i.e. 64-bit).

警告:请不要回复说使用 volatile 而不是 synchronized 是预先优化的情况;我很清楚如何/何时使用 synchronized 但在某些情况下 volatile 更可取.例如,在定义用于单线程应用程序的 Spring bean 时,我倾向于使用 volatile 实例变量,因为不能保证 Spring 上下文会在主线程中初始化每个 bean 的属性.

Caveat: Please do not reply saying that using volatile over synchronized is a case of pre-optimisation; I am well aware of how / when to use synchronized but there are cases where volatile is preferable. For example, when defining a Spring bean for use in a single-threaded application I tend to favour volatile instance variables, as there is no guarantee that the Spring context will initialise each bean's properties in the main thread.

推荐答案

不确定我是否正确理解您的问题,但是 JLS 8.3.1.4.volatile 字段 状态:

Not sure if I understand your question correctly, but the JLS 8.3.1.4. volatile Fields states:

一个字段可能被声明为 volatile,在这种情况下,Java 内存模型确保所有线程看到变量的一致值 (§17.4).

A field may be declared volatile, in which case the Java memory model ensures that all threads see a consistent value for the variable (§17.4).

也许更重要的是,JLS 17.7 double 和 long 的非原子处理 :

17.7 double 和 long 的非原子处理
[...]
出于 Java 编程语言内存模型的目的,对非易失性 long 或 double 值的单次写入被视为两次单独的写入:一次写入每个 32 位一半.这可能导致线程从一次写入中看到 64 位值的前 32 位,而从另一次写入中看到后 32 位的情况.对 volatile long 和 double 值的写入和读取始终是原子的. 对引用的写入和读取始终是原子的,无论它们是作为 32 位值还是 64 位值实现的.

17.7 Non-atomic Treatment of double and long
[...]
For the purposes of the Java programming language memory model, a single write to a non-volatile long or double value is treated as two separate writes: one to each 32-bit half. This can result in a situation where a thread sees the first 32 bits of a 64 bit value from one write, and the second 32 bits from another write. Writes and reads of volatile long and double values are always atomic. Writes to and reads of references are always atomic, regardless of whether they are implemented as 32 or 64 bit values.

也就是说,整个"变量受到 volatile 修饰符的保护,而不仅仅是两部分.这诱使我声称对 long 使用 volatile 比对 int 使用 volatile 甚至更重要,因为甚至不是read 对于非易失性 longs/doubles 是原子的.

That is, the "entire" variable is protected by the volatile modifier, not just the two parts. This tempts me to claim that it's even more important to use volatile for longs than it is for ints since not even a read is atomic for non-volatile longs/doubles.

这篇关于使用 volatile long 有什么意义吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆