2009-11-27 78 views
2

我有類似的代碼如下:同步上兩個或多個對象(爪哇)

public class Cache{ 
private final Object lock = new Object(); 
private HashMap<Integer, TreeMap<Long, Integer>> cache = 
    new HashMap<Integer, TreeMap<Long, Integer>>(); 
private AtomicLong FREESPACE = new AtomicLong(102400); 

private void putInCache(TreeMap<Long, Integer> tempMap, int fileNr){ 
    int length; //holds the length of data in tempMap 
    synchronized(lock){ 
    if(checkFreeSpace(length)){ 
    cache.get(fileNr).putAll(tmpMap); 
    FREESPACE.getAndAdd(-length); 
    } 
    } 
} 

private boolean checkFreeSpace(int length){  
    while(FREESPACE.get() < length && thereIsSomethingToDelete()){ 
    // deleteSomething returns the length of deleted data or 0 if 
    // it could not delete anything 
    FREESPACE.getAndAdd(deleteSomething(length)); 
    } 
    if(FREESPACE.get() < length) return true; 
    return false; 
} 
} 

putInCache由大約139螺紋的第二調用。我可以確定這兩種方法在cacheFREESPACE之間會同步嗎?另外,checkFreeSpace()多線程安全,即我可以確定一次只能調用一次該方法嗎?這段代碼的「多線程安全性」可以改進嗎?

+0

(在該代碼中使用'AtomicLong'沒有意義。) – 2009-11-27 17:31:52

回答

2

您通常不會在要直接控制訪問權的字段上同步。 要同步訪問的字段只能從同步塊中(同一對象上)訪問才能被視爲線程安全。您已在putInCache()中執行此操作。 因此,因爲checkFreeSpace()以非同步方式訪問共享狀態,所以它不是線程安全的。

+0

如果我將'putInCache()'聲明爲'synchronized',該怎麼辦?這會使這兩種方法「更安全」嗎? – Azimuth 2009-11-27 11:34:25

+0

@Azimuth您需要在字段級別保護訪問,這意味着訪問這些字段的所有方法都需要在同一個鎖定對象上進行同步。簡而言之,您還需要爲checkFreeSpace()添加一個同步塊。 – 2009-11-27 11:47:05

3

爲了讓您的問題得到充分回答,您需要顯示thereIsSomethingToDelete()和deleteSomething()方法的實現。

鑑於checkFreeSpace是一個公共方法(它確實需要嗎?),並且是不同步的,所以在putInCache()方法的synchronized塊同時運行時,可能會被另一個線程調用。這本身可能不會破壞任何東西,因爲看起來checkFreeSpace方法只能增加可用空間量,而不能減少可用空間量。

如果thereIsSomethingToDelete()和deleteSomething()方法沒有正確地使用同一個Object同步它們對緩存對象的訪問,那麼更嚴重的是什麼(以及代碼示例不允許我們確定這一點)鎖由putInCache()使用。

+0

感謝您的回覆。首先,'public'不是一個大問題,因爲這兩個方法只能被同一個類中的另一個方法調用。至於'thereIsSomethingToDelete()'和'deleteSomething()',事實上我沒有這些方法。他們的邏輯被包含在'checkFreeSpace'方法中,但如果我將所有的代碼放在這裏,那將會太麻煩。所以我們假設這些方法已經正確同步。 – Azimuth 2009-11-27 11:54:25

+0

對不起,我選擇了錯誤的方法來提問。請看看編輯後的版本。 – Azimuth 2009-11-27 12:00:19

+0

所以大概putInCache()是不是真正的私人然後要麼(否則該類實際上可以如何使用)。然後我認爲這個類是所描述的線程安全的,因爲只有當一個線程持有putInCache()同步塊建立的鎖時,才能進入可變狀態。 – Henry 2009-11-27 12:04:05