簡體   English   中英

對象鎖定私有類成員 - 最佳實踐? (JAVA)

[英]Object locking private class members - best practice? (Java)

前幾天我問了一個類似的問題 ,但對回復不滿意,主要是因為我提供的代碼有一些人們關注的問題。

基本上,在Java中鎖定私有成員的最佳做法是什么? 假設每個私有字段只能單獨操作而不能一起操作(比如下面我的Test類示例),你應該直接鎖定每個私有字段(例1),還是應該使用每個私有字段的一般鎖定對象來鎖定(例2)?

示例1:直接鎖定私有字段

class Test {
  private final List<Object> xList = new ArrayList<Object>();
  private final List<Object> yList = new ArrayList<Object>();

  /* xList methods */ 

  public void addToX(Object o) {
    synchronized(xList) {
      xList.add(o);
    }
  }

  public void removeFromX(Object o) {
    synchronized(xList) {
      xList.remove(o);
    }
  }

  /* yList methods */ 

  public void addToY(Object o) {
    synchronized(yList) {
      yList.add(o);
    }
  }

  public void removeFromY(Object o) {
    synchronized(yList) {
      yList.remove(o);
    }
  }
}

示例2:每個私有字段使用鎖定對象

class Test {
  private final Object xLock = new Object();
  private final Object yLock = new Object();
  private List<Object> xList = new ArrayList<Object>();
  private List<Object> yList = new ArrayList<Object>();

  /* xList methods */ 

  public void addToX(Object o) {
    synchronized(xLock) {
      xList.add(o);
    }
  }

  public void removeFromX(Object o) {
    synchronized(xLock) {
      xList.remove(o);
    }
  }

  /* yList methods */ 

  public void addToY(Object o) {
    synchronized(yLock) {
      yList.add(o);
    }
  }

  public void removeFromY(Object o) {
    synchronized(yLock) {
      yList.remove(o);
    }
  }
}

我個人更喜歡第二種形式。 沒有其他的代碼在所有可以使用該參考(除非反射,調試的API等)。 您無需擔心列表的內部詳細信息是否嘗試在其上進行同步。 (你在列表上調用的任何方法顯然都可以訪問this ,因此可以同步它。)你純粹使用它來鎖定 - 所以你也在“我是一個鎖”和“我之間分離了關注點列表“。

我發現這樣可以更容易推理顯示器,因為您可以輕松查看使用它的所有可能代碼。

您可能希望創建一個純粹用作監視器的單獨類,並使用toString()的覆蓋來幫助診斷。 它還可以使變量的目的更清晰。

誠然,這種方法的確需要更多的內存,而且通常你不必擔心代碼鎖定在this ...但我個人覺得分離關切,並不必擔心代碼是否鎖本身勝過的好處效率成本。 如果由於某種原因發現“浪費”的對象性能瓶頸(並且在分析了可能要同步的類中的代碼之后),您總是可以選擇第一個表單。

(就我個人而言,我希望Java和.NET 都沒有 “每個對象都有一個相關的監視器”路徑,但這是另一天的咆哮。)

例1更好。 由於xListfinal ,因此它們非常適合同步。 不需要額外的鎖定對象,不必要地使代碼復雜化並消耗內存。 只確保列表本身永遠不會暴露給外界破壞封裝和線程安全。

但請考慮:

讓我們這樣說:第二種方法使用更多代碼 - 這些額外代碼會給你帶來什么? 就並發性而言,兩者完全相同,因此從應用程序設計的大局來看,它必須是其他方面。

即使你確定你正在進行鎖定的對象永遠不會改變,我發現使用特殊對象只是為了鎖定更令人放心。 它使它更透明。 如果該類將來被其他人顯着擴展和/或修改,他可能會找到使xList非最終版的理由,而不會注意到它用於鎖定。 這很快就會導致問題。 線程安全並非易事,並且在代碼發展時會變得更加復雜,因此盡可能清晰且安全。 與診斷線程安全問題的成本相比,具有用於鎖定的單獨對象的成本較小。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM