【问题标题】:java synchronized method - how does it workjava同步方法 - 它是如何工作的
【发布时间】:2013-01-09 18:17:51
【问题描述】:

我想我知道这一点,但希望得到确认。

显然同步会阻止其他线程访问它,但我看到了很多例子,例如

   public synchronized void setValue(int value)
   {
       balance=value;
   }

我的想法是对的吗,如果方法像上面那样只做一行,那么同步就没有意义了。

谢谢

【问题讨论】:

  • 如果您只获取或设置balance,您可以设置为volatile,但您无法以原子方式获取和设置。

标签: java synchronized


【解决方案1】:

我的想法是对的吗,如果方法像上面那样只做一行,那么同步就没有意义了。

没有。您似乎认为同步仅意味着原子性。

但它实际上提供的远不止这些——特别是,它保证:

  • 原子性,这对于单行分配没有用(除了下面的边界情况)
  • 可见性
  • 防止重新排序
  • 互斥:同一监视器上同步的 2 个方法不能同时运行

在您的示例中,如果没有同步,您无法保证如果一个线程调用您的方法而另一个线程随后读取 balance,则第二个线程将看到更新的值。

请注意,必须确保两端的可见性:写入和读取需要同步,使用相同的监视器。所以 getter getBalance 也需要同步化。

边框double and long assignements are not guaranteed to be atomic。因此,即使在像下面这样的单行示例中,如果没有 synchronized 关键字,也有可能一个线程更新双精度的前 32 位,而另一个线程更新后 32 位,从而创建一个新的混合平衡变量。

public synchronized void setValue(double value) {
    balance = value;
}

【讨论】:

  • 不过,“阅读”方法也必须同步才能实现。
【解决方案2】:

它不仅阻止其他线程访问此方法:它还阻止其他线程访问具有相同锁的任何块或方法(此处为实例)。

关键是,如果另一个同步方法更长,您可以确保不会同时运行这个方法。

如果其他方法依赖于balance 变量在其执行期间不发生变化,这一点很重要。

【讨论】:

  • 好的,我想我明白了。所以它会锁定所有在类中同步的方法。
  • @MatthewSmith 不完全是:它锁定了调用此方法的对象的 instance。但由于锁是协作的,其他访问该值的方法也必须同步。
【解决方案3】:

同步方法做了两件事:

  • 不允许超过 1 个线程执行该方法
  • 将线程内存缓存与共享内存同步。

在您的情况下,只有一个线程能够更新该变量,并且所有其他线程都将在变量 balance 中看到最新数据。

如果没有同步,其他线程将使用(很可能)他们缓存的balance 值,因此您将在程序执行后得到不一致的balance 值。

您可以在presentation 中找到对您的问题的非常好的解释。

【讨论】:

    【解决方案4】:

    多个线程可以调用不同值的 setValue 方法。因此,如果您真的想确保一个线程的更改对另一个线程可见,则应该同步方法。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-10-19
      • 1970-01-01
      • 2013-11-08
      • 1970-01-01
      • 1970-01-01
      • 2015-09-02
      • 2015-07-27
      相关资源
      最近更新 更多