通常我會鎖定類似下面的關鍵部分。使用密鑰的同步訪問的代碼塊
public class Cache {
private Object lockObject = new Object();
public Object getFromCache(String key) {
synchronized(lockObject) {
if (cache.containsKey(key)) {
// key found in cache - return cache value
}
else {
// retrieve cache value from source, cache it and return
}
}
}
}
的想法是我避免出現競爭狀況可能導致數據源被擊中多次與鍵被添加到緩存中多次。
現在如果兩個線程在大約相同的時間不同緩存鍵進來,我仍然會阻礙之一。
假設鍵獨一無二的 - 將鎖仍然鎖定在重點工作?
我認爲它不會工作,因爲我知道對象引用應該是相同的鎖才能生效。我想這歸結於它如何檢查平等。
public class Cache {
public Object getFromCache(String key) {
synchronized(key) {
if (cache.containsKey(key)) {
// key found in cache - return cache value
}
else {
// retrieve cache value from source, cache it and return
}
}
}
}
號你需要保護的資源的緩存,而不是重點。你的建議沒有意義。 – EJP
通常,密鑰會散列到鎖對象的數組中以避免實例問題。這被稱爲條帶化,其中條帶(資源)通過該鎖保護免受任何突變。在你的緩存的例子中,這被稱爲memoization來避免[緩存踩踏](https://en.wikipedia.org/wiki/Cache_stampede),通過鎖定內部散列表項來完成。爲了避免鎖定讀取,這將使用樂觀的獲取和回退(雙重檢查鎖定)。 [咖啡因](https://github.com/ben-manes/caffeine)和其他緩存實現這種技術。 –
謝謝Ben,你的解釋很有用。我將介紹在密鑰上散列的鎖數組。 – Avner