2013-11-14 54 views
2

我正在處理一個代碼,它將輸入資源列表並嘗試鎖定其中的每一個。如果有人失敗,它會努力釋放所有資源上的鎖。這意味着要麼「所有」資源有鎖或根本沒有。我有兩種方法,我沒有看到任何顯着的優勢。這種情況下的標準編碼實踐是什麼?是否有任何設計模式的名稱?一個函數應該共享兩個責任,還是我們應該使用狀態檢查函數

OPTION 1: 

// one function taking on 2 responsibilities. appears bad to have unlock code in locking function 
public boolean getLock(List<Resource> resources) { 
    for (Resource r : resources) { 
      if (! Lock.getLock(r)) { 
       releaseLocks(resources); 
       return false; 
      } 
    } 
    return true; 
} 

OPTION 2: 

    public boolean getLock(List<Resource> resources) { 
     for (Resource r : resources) { 
       if (! Lock.getLock(r)) { 
        return false; 
       } 
     } 
     return true; 
    } 

    public boolean stateChecker(List<Resource> resources) { 
      if (!getLock(resouces)) { 
       releaseLocks(resources); 
       return false; 
      } 
      return true; 
    } 
+0

很多都會回到上下文中,我個人主要嘗試使用第二種選擇,根據需要(也就是說,只有一個資源可以鎖定)你可能需要第一個,但你也可以爭辯說,如果你嘗試獲得一個已經存在鎖的新鎖,你也可以拋出一個異常 – MadProgrammer

+0

這裏主要的問題是所有的步驟總是試圖鎖定資源**爲了避免死鎖或活鎖 –

+0

一些想法。鎖是資源的屬性 - 即爲什麼不是(布爾)r.lock(),(布爾值)r.isLocked(),r.unlock()?如果這是他們可以'同步'(如果需要 - 如果沒有,爲什麼你鎖定他們呢?)它看起來像所有這些方法可能是靜態的(目前給出)。無論如何,它們應該是最終的。什麼會阻止其他的東西(另一個線程,請求,什麼)釋放一個獲得的鎖,當它不應該?資源是接口還是具體類?其中任何一項都可能影響如何最好地保護這些資源。 – Paul

回答

0

函數應該總是指向一個單一的responsibility。儘管選項1似乎更加優雅,同時也減少了代碼的數量,但對於可維護性標準視圖而言,當您重新訪問時,對於某個人或您自己來說很難解釋功能的目的。

可能是一個奇怪的例子,只是陳述一個實時的例子,我們都在我們的生活中的父親,兄​​弟,丈夫等等等等,扮演多重角色,但我們必須爲這些角色及其責任的獨立boxes

沒有specific advantage,但它總是很好的保持你的職責限於角色定義。

+1

我同意上面的評論......但不涉及資源管理(鎖定,同步等)。在一個步驟中查詢和鎖定資源是非常普遍的習慣用法。事實上,在同步的多線程代碼中,這是*基本的*,否則當您嘗試鎖定資源時(雖然它不是在您查詢時),資源可能已被鎖定。在這一點上,你必須檢查鎖定工作(所以你再次查詢,實際上),或者你必須爲異常做好準備。 – Paul

0

相反,我沒有看到後者的選擇有什麼優勢。名字是「stateChecker」,但它顯然不僅僅是檢查狀態,它試圖鎖定資源。

我會使用選項1並命名方法tryToLock(List<Resource> resources)或類似。

1

你的第二個選項不是解鎖(部分)獲得的'鎖',即使它沒有得到他們所有人。 (或者getLocks()應該是私人的?)那麼這些資源如何解鎖以釋放它們呢?一種獲得所有鎖定或保證不鎖定的方法已經獲得了更好的聲音。 (如果沒有保證那麼如何將這些不斷被釋放,BTW?)

如果可能的話我會嘗試做這樣的事情:

interface ResourceUpdater { 
    public void useResources(List<Resource> rs); 
} 

public static boolean withResources(List<Resource> rs, ResourceUpdater updater) { 
    // lock/unlock would ideally be private (or perhaps package private). 
    // I'm also assuming the unlockAll() will be a no-op on the non-locked resources 
    try { 
     if(!lockAll(rs)) 
      return false; 
     updater.useResources(rs); 
     return true; 
    } 
    finally { 
     unlockAll(rs); 
    } 
} 

這裏的關鍵是要鎖定和解鎖你如何使用資源的實現細節:想要使用它們的客戶端代碼不需要意識到鎖定的機制,只要它總是使用這種方式來更新資源。

確切地說,您在哪裏嘗試......最終取決於您的鎖定/解鎖和您的操作的故障特徵。 (您可能想嘗試在單獨的try ... catch中解鎖每個資源,以確保至少有一個嘗試用於解鎖每個資源。另外,useResources()可能需要一個返回值,它是然後從withResources()返回

相關問題