【问题标题】:Java volatile necessary with synchronized access?Java volatile 需要同步访问吗?
【发布时间】:2015-12-07 21:50:35
【问题描述】:

在以下情况下,volatile 是多余的吗?删除volatile 在这里会有什么不同吗?或者,离开 volatile 但删除同步块和同步修饰符在这里会有什么不同吗?

private volatile boolean registered;

synchronized boolean registered() {
  return registered;
}

void setRegistered(boolean registered) {
  synchronized (this) {
    this.registered = registered;
  }
}

【问题讨论】:

  • 可能值得注意的是,synchronized 语句可能是不必要的(除非您希望在我们看不到的其他同步块期间不调用这些方法)。在这种情况下,使用synchronized 封装volatile 变量违背了volatile 状态的目的。

标签: java concurrency synchronized volatile


【解决方案1】:

不,除非您有其他未显示的访问权限,否则registered 没有volatile 也可以。

我认为删除volatile 会稍微加快代码速度。但我认为删除volatile 的主要好处是它为维护者清理了代码。

在这种情况下,volatile 和我可以看到的同步方法之间没有区别,因此请使用其中一个。 (除了同步方法使您用来保护registered 字段的对象public,这可能好坏参半。私有volatile 保持同步锁私有。)


如果您有这样的课程,请尝试澄清最后一条语句:

public class Reg {
    private boolean registered;

    synchronized boolean registered() {
      return registered;
    }

    void setRegistered(boolean registered) {
      synchronized (this) {
        this.registered = registered;
      }
    }
}

然后你创建一个新的实例:

public class Test {
  public static Reg reg;
  public void static main( String... args ) {
     reg = new Reg();
     synchronized( reg ) {
            // do stuff
     }
  }
}

Test 中的锁被持有时,任何其他试图访问reg.registered() 的人都会阻塞,直到该锁被释放。该锁对任何可以看到该对象的人都是公开的。这可能是好是坏。它允许其他类控制对您的方法的访问,这可能有利于原子性,但它也可能将一些线程控制烘焙到源代码库中,在那里它被分散到各处,而不是仅仅被一个类封装。好和坏。可能还有其他的例子来说明为什么这可能是好是坏,这只是一个。

【讨论】:

  • 您能解释一下将对象公开是什么意思吗?你是说this 的班级会公开吗?
  • “除非您有其他访问权限”——包括内部访问权限。如果此类仅通过提供的访问器和修改器方法接触成员变量registered,则同步它们可以充分保护变量,但如果它也通过其他非同步实例方法直接访问,则不会。
  • @JohnBollinger 是的,如果我想对这个类做更多的事情或“面向未来”它,我可能更喜欢 volatile 而不是同步部分。
  • 好吧,this 始终是公开的。如果我在您的对象上调用Reg reg = new Reg(),则reg 等于this。任何可以在您的类上调用 ctor 或通过某种工厂方法获取对象引用的人始终可以使用它。
  • 当然,我认为这就是它的实际作用,尽管volatile 从未真正持有过锁。
猜你喜欢
  • 2014-05-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-03-13
  • 2010-09-23
  • 2016-07-25
  • 1970-01-01
相关资源
最近更新 更多