【问题标题】:When are arguments assigned for synchronised methods?什么时候为同步方法分配参数?
【发布时间】:2021-01-18 15:06:28
【问题描述】:

我不记得在调用 synchronized 方法时分配参数的时间。

public int methodA() { return ... }

public synchronized void methodB(int arg) {}

当从多个线程调用methodB时

methodB(methodA());

我知道线程被阻塞,直到前一个线程完成运行方法 B。 我的问题是什么时候分配 arg ? (或者说何时调用 methodA() ?)。 是在阻塞发生之前还是之后?

【问题讨论】:

  • @JiaLi 请确保您的代码在发布前编译。
  • @BeUndead 已指定。相当于将方法体包装在synchronized (this) { ... } 块中。
  • methodA() 在阻塞前被调用。否则,methodA() 的行为也会像 synchronized 一样。您应该想到的方式就像您调用 methodA() 并将其返回值分配给一个局部变量,然后您将其传递给 methodB
  • @JohnKugelman:对于方法结果未在方法中使用并且对系统没有影响的情况,我留下了一些宽大处理 - 我不知道语言是否指定调用methodA() 必须执行。例如,如果它只是return nulls,我不知道它是否被内联。
  • @BeUndead:好吧,如果优化是相关的,那么 VM 将锁定粗化作为优化选项,这可能会使事情复杂化。虽然没有看到优化方法A如何改变事情。

标签: java multithreading synchronized


【解决方案1】:

MethodA 首先执行。在执行线程尝试进入 methodB 之前,不会获取调用 methodB 的对象的内在锁。

这是在 JLS 中,请参阅 https://docs.oracle.com/javase/specs/jls/se15/html/jls-17.html#jls-17.1

同步方法(第 8.4.3.6 节)在调用时自动执行锁定操作;在锁定操作成功完成之前,它的主体不会被执行。如果该方法是一个实例方法,它会锁定与调用它的实例相关联的监视器(即,在方法体执行期间将被称为 this 的对象)。如果该方法是静态的,它会锁定与 Class 对象关联的监视器,该对象表示定义该方法的类。如果方法主体的执行已经完成,无论是正常的还是突然的,都会在同一个监视器上自动执行解锁操作。

JLS 表示在调用方法时获取锁。在 methodA 完成并提供返回值之前,不会调用 MethodB。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-03-17
    • 2019-08-27
    • 2015-04-05
    • 1970-01-01
    • 2012-08-13
    • 2018-07-14
    • 2015-02-20
    相关资源
    最近更新 更多