Ehcache & 多线程 : how to lock when inserting to the cache?

标签 ehcache

假设我有一个多线程应用程序,其中有 4 个线程共享一个 (Eh) 缓存;缓存存储 UserProfile 对象以避免每次都从数据库中获取它们。

现在,假设所有这 4 个线程同时请求 ID=123 的同一个 UserProfile - 而且它还没有被缓存。要做的是查询数据库并将获得的 UserProfile 对象插入到缓存中,以便以后可以重用。

但是,我想要实现的是这些线程中只有一个(第一个)查询数据库并更新缓存,而其他 3 个线程等待(排队)完成...然后获取 UserProfile直接从缓存中获取 ID=123 的对象。

你通常如何实现这种场景?使用Ehcache的locking/transactions?或者更确切地说是通过这样的事情? (伪代码)

public UserProfile getUserProfile(int id) {
    result = ehcache.get(id)
    if (result == null) {  // not cached yet
        synchronized {  // queue threads
            result = ehcache.get(id)
            if (result == null) {  // is current thread the 1st one?
                result = database.fetchUserProfile(id)
                ehcache.put(id, result)
            }
        }
    }
    return result
}

最佳答案

这叫做 Thundering Herd问题。

锁定有效,但它非常有效,因为锁比您想要的更宽。您可以锁定单个 ID。

你可以做两件事。一种是使用 CacheLoaderWriter .它将加载丢失的条目并以正确的粒度执行锁定。这是最简单的解决方案,即使您必须实现加载程序编写器。

备选方案更为复杂。您需要某种行锁定算法。例如,您可以这样做:

private final ReentrantLock locks = new ReentrantLocks[1024];
{
    for(int i = 0; i < locks.length; i)) {
        locks[i] = new ReentrantLock();
    }
}

public UserProfile getUserProfile(int id) {
    result = ehcache.get(id)
    if (result == null) {  // not cached yet
        ReentrantLock lock = locks[id % locks.length];
        lock.lock();
        try {
            result = ehcache.get(id)
            if (result == null) {  // is current thread the 1st one?
                result = database.fetchUserProfile(id)
                ehcache.put(id, result)
            }                
        } finally {
            lock.unlock();
        }
    }
    return result
}

关于Ehcache & 多线程 : how to lock when inserting to the cache?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53125061/

相关文章:

Spring 缓存与缓存管理器

java - 为什么 hibernate 不从二级缓存加载持久实体?

java - EhCache缓存和CacheWriter刷新

spring - 用 Spring 智能地获取 EhCache 实例

ehcache - 我可以对不同类中的方法使用相同的缓存名称来使用 ehcache 进行缓存吗

java - Hibernate & EhCache : net. sf.ehcache.Statistics 未填充?

java - ehcache 获取timeToIdleSeconds的运行时间

java - 当进程被终止时,Ehcache 不会刷新到磁盘

java - 使用Ehcache时出现ClosedChannelException异常

java - 用java加载缓存中的数据