7

我想我知道这一点,但希望得到证实。

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

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

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

谢谢

4

4 回答 4

17

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

不,您似乎认为同步仅意味着原子性。

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

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

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

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

边界情况不保证双重和长赋值是原子的。因此,即使在下面这样的单行示例中,如果没有 synchronized 关键字,一个线程也可能更新双精度的前 32 位,而另一个线程更新后 32 位,从而创建一个新的混合平衡变量。

public synchronized void setValue(double value) {
    balance = value;
}
于 2013-01-09T18:20:33.650 回答
2

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

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

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

于 2013-01-09T18:19:19.607 回答
1

同步方法做了两件事:

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

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

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

您可以在此演示文稿中找到对您的问题的非常好的解释。

于 2013-01-09T18:22:22.387 回答
0

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

于 2013-01-09T18:21:31.903 回答