【问题标题】:Does synchronized work for all methods in a class or only 1?同步是否适用于类中的所有方法或仅适用于 1?
【发布时间】:2021-03-21 19:43:36
【问题描述】:

例如类 1 的线程 1 访问子类 A 的同步方法 1。然后类 2 的线程 2 访问同一个子类 A 的同步方法 1。这里一切正常。

如果我让类 3 中的线程 3 访问子类 A 的同步方法 2,它是否仍然禁止线程 1 和线程 2 在方法 2 执行其操作时访问方法 1?如果没有,我该如何实现?

【问题讨论】:

  • doc: "对于类(静态)方法,使用与方法类的 Class 对象关联的监视器。对于实例方法,与 this(方法所针对的对象)关联的监视器被调用)被使用。”如果监视器相同,则一个线程必须等待
  • 是的,这是简短的回答。在方法 2 中休眠并查看。

标签: java multithreading synchronization


【解决方案1】:

JLS, § 17.1 对此非常冗长:

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

Oracle's official tutorial on synchronized Methods 措辞更容易理解:

...

  • 首先,对同一对象的同步方法的两次调用不可能交错。 ...

...

【讨论】:

    【解决方案2】:

    synchronized 方法只是编写主体为 synchronized 块的方法的快捷方式。这个;

    synchronized AnyType foobar(...) {
        doSomething();
    }
    

    只是写这个的捷径;

    AnyType foobar(...) {
        synchronized(this) {
            doSomething();
        }
    }
    

    更多详情请见Java synchronized method


    附言,

    如果我有来自第 3 类的线程 3...

    线程不是“来自类”。线程只是执行代码的对象。当你的程序创建一个新线程时,系统不记得也不关心哪个类的什么方法创建了它,系统甚至不记得也不关心其他线程是什么创建的。

    【讨论】:

      【解决方案3】:

      你问(假设实例方法而不是静态方法):

      Thread 1 ---executes--> classA.method1
      Thread 2 ---executes--> classA.method1
      

      然后

      Thread 3 ---executes--> classA.method2
      

      method1 和 method2 都是同一个类中的同步实例方法。

      结果method1method2 都具有相同的 monitorthis 实例),并且一次一个线程将获得锁并执行 method1method2 并且没有其他线程将除非执行方法的线程退出并且监视器可以被锁定。

      理解的关键是监视器对于所有两种方法都是相同的

      【讨论】:

        猜你喜欢
        • 2013-05-29
        • 2019-09-08
        • 2016-09-02
        • 1970-01-01
        • 2023-03-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-10-25
        相关资源
        最近更新 更多