【问题标题】:Java multithreaded getters and settersJava 多线程 getter 和 setter
【发布时间】:2014-07-16 11:52:08
【问题描述】:

假设我有一个实例变量,并且我有 setter 和 getter。

代码 1:

Class<T> {
    volatile T value;

    public synchronized void set(T v) {
        if(value==null) {
            value=v;
        }

    }

    public T get() {
        return value;
    }
} 

代码 2:

Class<T> {
    static volatile T value;

    public synchronized void set(T v) {
        if(value==null) {
            value=v;
        }
    }

    public T get() {
        return value;
    }
}

我有两个问题

1) 静态易失状态字段和只有易失状态字段有什么区别?

2) 刚了解了 volatile 读/写的 release/acquire 概念,明白了 getter 不需要同步(因为缓存刷新)。但是 setter 需要同步吗?

【问题讨论】:

  • 第一个问题的答案与多线程无关 - 静态变量是静态变量。变量是否为 volatile 无关紧要。
  • @assylias 不,考虑一下:class X implements Runnable { private static Object o; public void run() { o = new Object(); }}。在这种情况下,变量是否为静态很重要。
  • @Absurd-Mind 我没有说static没有用,我只是说static关键字的含义对于非易失性和易失性变量是一样的。
  • @assylias:谢谢你的回复,很有道理。

标签: java multithreading static volatile


【解决方案1】:

让我们从你的第二个问题开始:

我认为您应该在 setter 中使用同步块的原因是您对 value 执行了两种不同的操作。检查value==null,然后设置value=v。虽然您确实在每个步骤中都有锁定,但它们之间没有锁定。所以这是可能的:

Thread1: lock value -> value==null (true) -> release value
Thread2: lock value -> value==null (true) -> release value
Thread1: lock value -> value=v -> release value;
Thread2: lock value -> value=v -> release value;

所以你仍然有竞争条件。

现在回到你的第一个问题:你应该使用 static 让你的类的任何实例都使用相同的变量 T 而不是拥有自己的变量。

【讨论】:

    【解决方案2】:

    在代码 2 中,以下是可能的:

    Thread1: calls set(X) on instance1
    Thread1: value is null, entering inside if
    Thread2: calls set(Y) on onstance2
    Thread2: value is null, entering inside if
    Thread2: setting value = Y
    Thread1: setting value = X
    

    问题是在你的类的实例上获取锁,而不是类本身。如果您将setget 方法都更改为static,那么它会再次正常工作。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-09-13
      • 1970-01-01
      • 1970-01-01
      • 2016-02-19
      • 1970-01-01
      • 2016-12-08
      相关资源
      最近更新 更多