Java 哪个更有效?为什么?

Java 哪个更有效?为什么?,java,multithreading,concurrency,Java,Multithreading,Concurrency,在下面两种同步策略中,哪一种是优化的(如处理和生成的字节码),以及应该使用其中一种的场景 public synchronized void addName(String name) { lastName = name; nameCount++; nameList.add(name); } 或 还有什么是处理并发的可取方法: 使用java.util.concurrent包 使用上述低级方法 使用Job或UIJobAPI(如果在eclipsepde环境中

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

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

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

  • 使用
    java.util.concurrent
  • 使用上述低级方法
  • 使用
    Job
    UIJob
    API(如果在eclipsepde环境中工作)

  • 谢谢

    说不上来,因为这两个代码片段并不相等

    差异(添加调用的同步性不足)可能是显著的,但可能不是。从你给我们的东西来看,很难说。

    • 您更新的两段代码在语义上是相同的。但是,使用第二部分中的同步块可以实现更多的控制,因为您可以在不同的对象上同步,或者实际上,不同步不需要同步的方法部分
    • 在可能的情况下,使用
      java.util.concurrent
      比使用同步原语更可取,因为它允许您在更高的抽象级别上工作,并使用由非常熟练的人员编写并经过密集测试的代码
    • 如果您在EclipsePDE中工作,使用它的API很可能是首选,因为它与平台的其余部分相关联
    哪一个是优化的(如在处理和生成的字节码中)

    根据本发明,与同步块相比,同步方法生成的字节码更少。文章解释了原因

    文章片段:

    当JVM执行一个同步的方法时,执行线程识别出该方法的method_info结构设置了ACC_synchronized标志,然后它自动获取对象的锁,调用该方法,并释放锁。如果发生异常,线程将自动释放锁

    在上同步方法块 另一方面,绕过JVM的 内置支持获取 对象的锁和异常处理 并且要求功能 用字节码显式编写。如果 读取方法的字节码 使用同步块,您将 看到十几个额外的 管理此项的操作 功能。清单1显示了调用 要生成这两种方法,请使用同步方法 和一个同步块:

    编辑以处理第一条评论

    为了表扬其他SOER,这里有一个关于为什么要使用同步的好讨论。块我相信,如果您四处搜索,您可以找到更有趣的讨论:)


    我个人不需要使用同步。块锁定除此之外的另一个对象,但这是SOers指出的有关同步的一种用法。块。

    我知道这可能是一个例子,但如果您打算编写这样的代码,请三思

    在我看来,您似乎在复制信息,除非您看到需要对代码进行性能更改,否则不应该这样做。(这几乎是你永远不应该做的)

    • 如果您确实需要在多个线程中运行这些代码,我会使用Collections.synchronizedList将名称列表制作成一个同步列表
    • 姓氏应该是一个getter,它可以选择列表中的最后一个元素
    • nameCount应该是列表的大小

    如果您像现在这样做,那么还必须同步对引用变量的所有位置的访问,这将使代码的可读性大大降低,并且更难维护。

    从任何效率角度来看,这完全不重要

    拥有块的意义在于可以指定自己的锁。您可以选择封装在对象中的锁,而不是使用
    this
    ,这样您就可以更好地控制谁可以获得锁(因为您可以使该锁从对象外部无法访问)

    如果使用
    this
    作为锁(无论是在方法上放置synchronized还是在块上使用synchronized),程序中的任何内容都可以获得对象上的锁,并且很难对程序正在执行的操作进行推理


    限制对锁的访问可以让您在可判定性方面获得巨大的收益,拥有这种确定性比在某个地方删除字节码更有益。

    您可以删除所有锁:

    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;
        }
      }
    }
    
    类名{
    AtomicReference名称=新的AtomicReference();
    public void addName(最终字符串名){
    Node old=names.get();
    而(!names.compareAndSet(旧的,新的节点(旧的,名称))){
    old=names.get();
    }
    }
    公共字符串getName(){
    final Node=names.get();
    返回(node==null)?null:node.name;
    }
    静态类节点{
    最终节点父节点;
    最后的字符串名;
    节点(最终节点父节点、最终字符串名称){
    this.parent=parent;
    this.name=名称;
    }
    整数计数(){
    整数计数=0;
    节点p=父节点;
    while(p!=null){
    计数++;
    p=p.parent;
    }
    返回计数;
    }
    }
    }
    

    这基本上是一个Treiber堆栈实现。您可以获得大小和当前名称,并且可以轻松地对内容实现迭代器(尽管与示例中的迭代器相反)。根据您的需要,也可以使用替代的写上副本容器。

    感谢您指出遗漏的部分。我已经更新了代码片段。那么,
    语义相同
    是否意味着为它们生成的字节码相同?如果我喜欢其中一个而不是另一个,那么会有性能开销吗?@Favonius:不会,这意味着它们在同步方面会有相同的效果。我不知道这对性能是否有影响。拥有更多的字节码与此无关,因为只有机器码基因
    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;
        }
      }
    }