繁体   English   中英

哪个更有效,为什么?

[英]Which is more efficient and why?

在以下两个同步策略中,哪一个被优化(如在处理和生成的字节代码中)以及应该使用其中一个的场景。

public synchronized void addName(String name) 
{
       lastName = name;
       nameCount++;
       nameList.add(name);
}

要么

public void addName(String name) {
    synchronized(this) {
        lastName = name;
        nameCount++;
        nameList.add(name);
    }

}

还有什么是处理并发的可行方法:

  1. 使用java.util.concurrent
  2. 使用上面的低级方法
  3. 使用JobUIJob API(如果在eclipse PDE环境中工作)

谢谢

  • 您更新的两段代码在语义上是相同的。 但是,使用第二部分中的同步块可以让您进行更多控制,因为您可以在不同的对象上进行同步,或者实际上不同步不需要的方法部分。
  • 使用java.util.concurrent非常适合尽可能使用同步原语,因为它允许您在更高的抽象级别工作,并使用由技术娴熟的人员编写并密集测试的代码。
  • 如果你在eclipse PDE中工作,那么使用它的API很可能是可取的,因为它与平台的其他部分相关联。

哪一个被优化(如在处理和生成的字节代码中)

根据这篇IBM DeveloperWorks文章第1节 ,与synchronized块相比, synchronized方法生成的字节码更少 这篇文章解释了原因。

文章摘录:

当JVM执行synchronized方法时,执行线程识别方法的method_info结构设置了ACC_SYNCHRONIZED标志,然后它自动获取对象的锁,调用方法并释放锁。 如果发生异常,则线程会自动释放锁。

另一方面,同步方法块绕过JVM内置的对获取对象锁和异常处理的支持,并要求以字节代码显式写入功能。 如果您读取具有同步块的方法的字节代码,您将看到十几个额外的操作来管理此功能。 清单1显示了生成synchronized方法和synchronized块的调用:

编辑发表第一条评论

为了给其他SOers信用,这里有一个很好的讨论为什么人们会使用同步。 块。 如果你搜索一下,我相信你可以找到更多有趣的讨论:)

使用同步方法而不是同步块是否有优势?

我个人没有必要使用同步。 块锁定在比其他另一个目的this ,但是这是一个使用SOers指出关于同步。 块。

从任何效率的角度来看,这都无关紧要。

拥有块的重点是你可以指定自己的锁。 您可以选择封装在对象中的锁,而不是使用this锁,结果是您可以更好地控制谁可以获取锁(因为您可以从对象外部无法访问该锁)。

如果你使用this作为锁(无论你是在方法上放置同步还是使用块),程序中的任何东西都可以获得对象的锁定,并且更难以推断出你的程序正在做什么。

限制对锁的访问会使您获得可判断性的巨大收益,拥有这种确定性比在某处削减字节码更有利。

我知道这可能是一个例子,但是如果你打算编写这样的代码 - 再想一想。

对我而言,您看起来像是在复制信息,除非您发现需要对代码进行性能更改,否则不应该这样做。 (你几乎不应该这样做)。

  • 如果你真的需要这个是在多个线程中运行的代码,我会使用Collections.synchronizedList将nameList变为同步列表。
  • 姓氏应该是一个getter,它可以选择列表中的最后一个元素。
  • nameCount应该是列表的大小。

如果你像现在这样做了什么,你还必须同步访问引用变量的所有地方,这将使代码的可读性和可维护性更低。

您可以删除所有锁定:

class Names {
  AtomicReference<Node> names = new AtomicReference<Node>();

  public void addName(final String name) {
    Node old = names.get();
    while (!names.compareAndSet(old, new Node(old, name))) {
      old = names.get();
    }
  }

  public String getName() {
    final Node node = names.get();
    return (node == null) ? null : node.name;
  }

  static class Node {
    final Node parent;
    final String name;

    Node(final Node parent, final String name) {
      this.parent = parent;
      this.name = name;
    }

    int count() {
      int count = 0;
      Node p = parent;
      while (p != null) {
        count++;
        p = p.parent;
      }
      return count;
    }
  }
}

这基本上是Treiber堆栈实现。 您可以获取大小,当前名称,并且可以轻松地在内容上实现迭代器(尽管与示例中的迭代器相反)。 根据您的需要,也可以使用备用的写时复制容器。

不可能说,因为这两个代码片段不相同。

差异(缺少调用add的同步)可能很重要,可能不是。 从你给我们的东西不可能说出来。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM