簡體   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