【问题标题】:can I use synchronized to a final field?我可以使用同步到最终字段吗?
【发布时间】:2012-07-13 17:57:44
【问题描述】:

考虑下面的代码,我想让它成为一个线程安全的类,这样它就永远不会得到奇数:

class Test {
  private int value = 0;
  private final Object lock;

  public void add() {
    synchronized (lock) {
      value++;
      value++;
    }
  }

  public int getValue() {
    synchronized (lock) {
      return value;
    }
  } 
}

我现在对声明为 final 的 lock 字段表示怀疑,这有关系吗?还是会破坏线程安全?

我认为如果锁字段没有被声明为最终的,这应该是一个线程安全的类。如果这个结论有误,请指正,谢谢。

【问题讨论】:

标签: java final synchronize


【解决方案1】:

我现在对声明为 final 的 lock 字段表示怀疑,这有关系吗?

是的,它被认为是锁定final字段对象的最佳实践。

如果可以更改引用,则可以更改锁定的对象,从而破坏线程安全。

【讨论】:

    【解决方案2】:

    在 Java 中,同步是由锁定对象的某个隐藏字段完成的。同样 final 意味着 REFERENCE 是最终的,而不是对象本身。

    例子:

    final Bar bar = new Bar(); //bar hase property lock
    bar.lock = XYZ; //will work, object is not FINAL
    bar = new Bar(); //fail, the reference is FINAL
    

    【讨论】:

    • 对于它的价值,Java 中没有内置的构造来使“对象最终”。必须以编程方式强制执行不变性。
    【解决方案3】:

    应该没问题。甚至可能使它更安全,因为在执行期间不能简单地将其他东西分配给锁。

    【讨论】:

      【解决方案4】:

      您可以使用 ReadWriteLock 来实现相同的结果,并且实现安全。

      参考资料:

      http://docs.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/locks/ReadWriteLock.html

      http://www.javapractices.com/topic/TopicAction.do?Id=118

      【讨论】:

        【解决方案5】:

        如果您希望锁定一个实例,那么 final 是可以接受的。如果您希望在某个类上锁定或放置互斥锁,则将变量设为静态。

        【讨论】:

          【解决方案6】:

          当您尝试同步多个线程时,它们必须基于相同的对象引用/实例进行同步。这样可以确保它们同时基于相同的数据进行同步。

          希望这有点道理;您只需要基于最终变量而不是动态变量进行同步。

          如果方法修改了静态字段,则必须同步访问 此字段,即使该方法通常仅由单个 线。客户端无法执行外部操作 在这种方法上同步,因为无法保证 不相关的客户也会这样做,see

          【讨论】:

            猜你喜欢
            • 2022-10-16
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2021-06-18
            • 2011-12-10
            • 2013-05-30
            • 2023-03-23
            • 1970-01-01
            相关资源
            最近更新 更多