【问题标题】:Is it necessary to make this variable volatile?是否有必要使这个变量变得易变?
【发布时间】:2013-03-26 22:34:01
【问题描述】:

我正在观看“JAX London 2011”presentation on "Modern Java Concurrency"。在 43:20 - 43:40 的时间段内,一位观众说下面代码中的 shutdown 变量应该被声明为 volatile 并且演示者同意它(并说它在前面已经指出也一样,但他们只是没有修改演示文稿)。有问题的代码是:

public abstract class QueueReaderTask implements Runnable {

  private boolean shutdown = false;
  protected BlockingQueue<WorkUnit<String>> lbq;

  public void run() {
    while (!shutdown) {
      try {
        WorkUnit<String> wu = lbq.poll(10, TimeUnit.MILLISECONDS);
        if (wu != null) { doAction(wu.getWork()); }
      } catch (InterruptedException e) {
        shutdown = true;
      }
    }
  }

  public abstract void doAction(String msg);
  public void setQueue(BlockingQueue<WorkUnit<String>> q) { lbq = q; }
}

我的问题: 我不认为shutdown 应该声明为volatile。 我的理由是shutdownRunnable 的成员,每个任务/线程都将拥有该变量的不同私有副本。那么,为什么要设为volatile

但由于这已在 JAX 2011 中进行了讨论,因此我假设听众中有很多专业的 Java 开发人员。我不认为他们所有人都会错过这个! 那么,我错过了什么?

P.S:- 我可以理解,如果一个变量(可能)被多个线程共享,则应该声明一个变量volatile,就像在双重检查锁定模式中一样:

class Foo {
        private volatile Helper helper = null;
        public Helper getHelper() {
            if (helper == null) {
                synchronized(this) {
                    if (helper == null)
                        helper = new Helper();
                }
            }
            return helper;
        }
}

【问题讨论】:

    标签: java multithreading volatile


    【解决方案1】:

    每个任务/线程都将拥有该变量的不同私有副本。那么,为什么要让它“不稳定”呢?

    您是正确的如果 shutdown 布尔值仅在 QueueReaderTask 实例中修改。在那种情况下,shutdown 只被一个线程修改,不需要是volatile

    坦率地说,代码对我来说看起来很奇怪。为什么要捕获InterruptedException,设置shutdown 布尔值,然后循环退出。为什么现在只做以下事情?为什么要有shutdown 标志?

    while (true) {
      try {
        WorkUnit<String> wu = lbq.poll(10, TimeUnit.MILLISECONDS);
        if (wu != null) { doAction(wu.getWork()); }
      } catch (InterruptedException e) {
         Thread.currentThread().interrupt();
         return;
      }
    }
    

    也许帖子中删除了额外的代码?如果不是,我想知道这是否是从较大的代码部分复制和粘贴的,其中 shutdown 在方法调用中设置为 true also

    P.S:- 我可以理解,如果变量(可能)由多个线程共享,则应将其声明为“易失性”,如双重检查锁定模式:

    没错。一个典型的模式是 shutdown 是从另一个告诉线程停止处理的线程修改的。在这种情况下,它需要是volatile

    【讨论】:

    • 有人想解释一下-1吗?
    • 谢谢。我认为可以安全地假设“关闭”只能从 QueueReaderTask 实例中修改,因为: 'shutdown' 变量被声明为私有的。湾。该类没有“...”(意味着没有释义或遗漏代码)。 C。没有 setShutdown()。 d。该变量的含义似乎是:'如果我无法正确完成对队列中对象的处理,请关闭自己'。如果另一个线程无法正确处理队列中的对象,则该线程不应该关闭。
    • 我同意@VenkateshDhandapani。
    猜你喜欢
    • 2019-11-04
    • 1970-01-01
    • 2015-06-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-12
    相关资源
    最近更新 更多