通常我会锁定类似下面的关键部分。使用密钥的同步访问的代码块
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