【问题标题】:Is Java synchronized lock key the same for all synchronized methods of the same object?对于同一对象的所有同步方法,Java 同步锁键是否相同?
【发布时间】:2020-06-29 17:04:08
【问题描述】:

如果我有两个或多个同步方法,那么所有同步方法的锁定键是否相同?换句话说,如果一个线程处于同步方法中,那么如果任何其他线程想要访问某个 other 同步方法,那么即使方法不同,也必须等待第一个线程结束?

【问题讨论】:

  • 是的,只要在同一个对象上同步就可以了
  • 关于 SO 的类似问题太多了,甚至 SO 自己的搜索也单独找到了其中两个并将它们放在“相关”侧边栏中。
  • 提示:不要考虑同步方法。方法不需要保护。需要保护的是方法操作的数据。如果您有两个或多个可以从不同线程调用的方法来操作相同的数据,那么这些方法绝对应该锁定同一个锁。

标签: java concurrency synchronized


【解决方案1】:

是的,你是对的。 如需更详细的答案,请继续阅读。

来自我最喜欢的 Java 书籍,Head First Java

每个对象都有一把锁。大多数时候,锁是解锁的,并且 你可以想象一个虚拟钥匙和它坐在一起。对象锁进入 仅在有同步方法时播放。

当一个 对象有一个或多个同步方法,一个线程可以进入一个 仅当线程可以获取对象的键时才使用同步方法 锁!

锁不是每个方法,它们是每个对象。
如果一个对象有两个同步方法,这不仅仅意味着你 不能有两个线程进入同一个方法。这意味着你不能 有两个线程进入任何同步方法。

想想看。如果您有多种可能起作用的方法 在对象的实例变量上,所有这些方法都需要 受同步保护。
同步的目标是 保护关键数据。但请记住,您不会锁定数据本身, 您同步访问该数据的方法。

那又如何 当一个线程正在通过它的调用堆栈(开始 使用 run() 方法)并突然遇到同步方法?
线程识别出它需要该对象的密钥之前 它可以输入方法。它寻找密钥(这一切都由 虚拟机; Java 中没有用于访问对象锁的 API),如果 密钥可用,线程抓取密钥进入方法。
从那时起,线程就挂在那个键上,就像 线程的生命取决于它。线程不会放弃密钥,直到它 完成同步方法。
因此,当该线程正在等待时 关键,没有其他线程可以进入该对象的任何同步 方法,因为该对象的一个​​键将不可用。



TL;DR:

每个 Java 对象都有一个锁。
也就是说,锁不是每个方法,而是每个对象。
现在,锁只有一把钥匙。
大多数时候,锁是 解锁,没人关心。 但是如果一个对象有 synchronized 方法,一个 线程可以进入其中之一 synchronized 仅限方法 对象的锁 可用。换句话说, 仅当另一个线程没有 已经抓住了一个键(通过输入synchronized 函数)。

【讨论】:

    【解决方案2】:

    为了补充上面发布的答案,我将尽我所能解释:

    类中的同步方法可以是静态的也可以是非静态的

    • 对于静态方法,锁在类级别。因此,无论您拥有多少个不同的类实例,一次只有一个线程可以访问一个方法。如果该类的一个实例的第一个线程位于其中一个同步方法中,则另一个线程访问具有相同/不同类实例的同一类中的不同同步方法的相同方法将不得不等到第一个线程在班级水平。

    • 对于非静态方法,锁在实例/对象级别。这意味着来自此类的 2 个不同实例的 2 个线程可以同时访问同一个方法,因为锁定对象是此类的 2 个不同实例。

    【讨论】:

      猜你喜欢
      • 2011-03-04
      • 2023-04-04
      • 2013-04-25
      • 1970-01-01
      • 1970-01-01
      • 2012-03-20
      • 1970-01-01
      • 2015-12-21
      • 2012-09-06
      相关资源
      最近更新 更多