【问题标题】:Understanding and confusion over synchronization in javajava中同步的理解和困惑
【发布时间】:2013-10-14 06:38:56
【问题描述】:

假设我们有

class A {
    synchronized void m1() {
    }
    synchronized void m2() {
    }
    void m3() {
    }
    static void m6() {
        synchronized(this){
        }
    }
}

以及 A 类 a1&a2 的两个实例。

现在如果线程 t1 和实例 a1 调用方法 m1,只有在 t1 完成 m1 的执行之前,线程 t2 和实例 a1 不能执行方法 m1。并且 t2 与实例 a2 可以执行 m1()。

现在我的疑问是线程 t1 与 a1 可以在执行 m1 时并行执行其他方法(m1 除外)吗?

黑白同步块和同步方法有什么区别?只是区块的同步范围更小,所以效率更高?

我读过一篇文章,说明“如果作为参数提供给块的表达式计算为 null,则同步块可以抛出 java.lang.NullPointerException”。

我们总是使用“this”作为同步块的参数,所以只有并且总是在静态方法中使用同步块。因为我们不需要对象实例来执行静态方法。

我在哪里误解了它?

【问题讨论】:

  • we always use "this" as parameter to synchronized block。实际上在this 上同步被认为是不好的做法
  • we always use "this" as parameter to synchronized block 现在这是一个错误......
  • @ppeterka66 您能否解释一下我们应该使用什么样的表达式作为同步块的参数,因为我可以看到 Sotirios Delimanolis 的答案直接将 null 作为参数。你能举个例子来说明清楚吗?请
  • @ppeterka66 虽然synchronized(this) 可能是个坏习惯。只有当引用的this 可以公开访问时,才会如此。否则委派孩子synchronized(this) 完全没问题。
  • @JohnVint 同步时你是否使用this总是

标签: java multithreading synchronization


【解决方案1】:

我认为是的。

关于在 this 上同步 - 如果您在 'this' 或任何公开可见的对象上同步特定类的内部(甚至外部)逻辑,您将面临类外的某些东西可能“干扰”的风险抓住锁的东西。所以...每当您决定针对特定情况的锁定机制时,您需要权衡并在您的 API 中明确该对象的锁定策略是什么。

【讨论】:

    【解决方案2】:

    例如, synchronized(this){...} 将仅在实际临界区附近运行,并且仅在当前实例上运行,但 synchronized(otherInstance){...} 将与其他实例一起工作,而与当前实例无关

    【讨论】:

      【解决方案3】:

      现在如果线程 t1 和实例 a1 调用方法 m1,那么只有 具有实例 a1 的线程 t2 无法执行方法 m1 的限制 直到 t1 完成 m1 的执行。而 t2 与实例 a2 可以 执行 m1()。

      这是正确的。由于两个线程都是synchronized 在同一个实例上,所以第一个Thread 开始执行,第二个Thread 开始等待。

      现在我的疑问是线程 t1 与 a1 是否可以执行其他 方法(除了 m1)在执行 m1 时是否并行?

      是的,这称为可重入同步。看看end of this tutorial.

      黑白同步块和同步方法有什么区别?是 不同之处仅在于该块的范围较小 同步那么高效吗?

      synchronized 块可用于任何实例。 synchronized 方法在 this 上隐式同步。尽量只在实际的临界区周围使用synchronized 块。

      我看过一篇文章说“同步块可以抛出 java.lang.NullPointerException 如果提供的表达式阻止为 参数计算结果为 null"。

      以下

      synchronized(null) {...}
      

      会抛出NullPointerException

      【讨论】:

      • synchronized methodName(...){} 不等于methodName(...){synchronized(this){}} 时是否存在边缘情况?我猜如果方法体编辑了可以传递给它的参数?我问是因为您的回答说明了为什么同步块可以比同步方法更好,但并没有真正说明相反的情况。
      • @Cruncher 我不这么认为。每个方法调用都有自己的参数副本。
      • @cruncher 你说的其他方式是什么意思?
      • 我的意思是,除了节省一行代码之外,使用同步方法还有什么真正的优势吗?
      • @Cruncher 据我所知没有。 See the example in this JLS chapter。它说它们是等价的。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-03-01
      • 2021-09-04
      • 1970-01-01
      相关资源
      最近更新 更多