java java同步方法 - 它是如何工作的

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/14243790/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-31 15:35:46  来源:igfitidea点击:

java synchronized method - how does it work

javasynchronized

提问by Matthew Smith

I think I know this, but would like it confirming.

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

Obviously the synchronized blocks other threads from accessing it, but I see and awful lot of examples such as

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

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

Am I right in thinking, that if the method only does one line like the above, then there is no point in it being synchronized.

我的想法是否正确,如果该方法只执行上述一行,那么同步就没有意义了。

Thanks

谢谢

回答by assylias

Am I right in thinking, that if the method only does one line like the above, then there is no point in it being synchronized.

我的想法是否正确,如果该方法只执行上述一行,那么同步就没有意义了。

No. You seem to believe that synchronized only means atomicity.

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

But it actually provides more than that - in particular, it guarantees:

但它实际上提供了更多 - 特别是,它保证:

  • atomicity, which is not useful for a one line assigment (except in border case below)
  • visibility
  • prevents reordering
  • mutual exclusion: 2 methods synchronized on the same monitor can't be run concurrently
  • 原子性,这对一行分配没有用(下面的边界情况除外)
  • 能见度
  • 防止重新排序
  • 互斥:在同一个监视器上同步的 2 个方法不能同时运行

In your example, without synchronized, you have no guarantee that if a thread calls your method and another reads balancesubsequently, that second thread will see the updated value.

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

Note that visibility must be ensured at both ends: the write AND the read need to be synchronized, with the same monitor. So the getter getBalancewill need to be syhcnronized too.

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

Border case: double and long assignements are not guaranteed to be atomic. So even on a one line example like below, without the synchronized keyword, it would be possible that one thread updates the first 32 bits of the double and another thread updates the last 32 bits, creating a new mixed up balance variable.

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

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

回答by Denys Séguret

It doesn't only block other threads accessing this method : it blocks other threads accessing any block or method with the same lock (here the instance).

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

The point is that if another synchronized method is longer, you'll be assured this one won't be run at the same time.

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

This is important if the other method relies on the balancevariable not changing during its execution.

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

回答by Tom

Synchronized method does two things:

同步方法做两件事:

  • Does not allow more than 1 thread to execute that method
  • Synchronizes thread memory cache with shared memory.
  • 不允许超过 1 个线程执行该方法
  • 将线程内存缓存与共享内存同步。

In your case only one thread will be able to update that variable and also all other threads will see up to date data in the variable balance.

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

Without synchronization other thread would user (that's very likely) their cached value of balanceso you would get inconsistent balancevalue after program execution.

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

You can find very nice explanation of your problem in this presentation.

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

回答by Subin Sebastian

multiple threads could call setValue method with different value. So if you really want to ensure that one threads change is visible to another thread then method should be synchronized.

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